Skip to content

Commit 81ae5ed

Browse files
committed
v0.0.2
1 parent e1f49a1 commit 81ae5ed

17 files changed

Lines changed: 674 additions & 159 deletions
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { LayoutPath, LayoutDivider, Layout } from "./layout_config.ts";
2+
/**
3+
* Determines which panel or divider is located at a given position in the
4+
* layout.
5+
*
6+
* @param row - Vertical position as a fraction (0-1) of the container
7+
* height
8+
* @param column - Horizontal position as a fraction (0-1) of the
9+
* container width
10+
* @param layout - The layout tree to search
11+
* @param check_dividers - Whether `LayoutDivider` intersection should be
12+
* checked, which oyu may not want for e.g. `drop` actions.
13+
* @returns The panel path if over a panel, a divider if over a resizable
14+
* boundary, or null if outside all panels
15+
*/
16+
export declare function calculate_intersection(column: number, row: number, layout: Layout, check_dividers: false): LayoutPath;
17+
export declare function calculate_intersection(column: number, row: number, layout: Layout, check_dividers: true): LayoutPath | null | LayoutDivider;
18+
export declare function calculate_intersection(column: number, row: number, layout: Layout, check_dividers?: boolean): LayoutPath | null | LayoutDivider;

dist/common/calculate_split.d.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { type Layout, type LayoutPath } from "./layout_config";
2+
/**
3+
* Calculates an insertion point (which may involve splitting a single
4+
* `"child-panel"` into a new `"split-panel"`), based on the cursor position.
5+
* *
6+
* @param col - The cursor column.
7+
* @param row - The cursor row.
8+
* @param panel - The `Layout` to insert into.
9+
* @param slot - The slot identifier where the insert should occur
10+
* @param drop_target - The `LayoutPath` (from `calculateIntersect`) of the
11+
* panel to either insert next to, or split by.
12+
* @returns A new `LayoutPath` reflecting the updated (maybe) `"split-panel"`,
13+
* which is enough to draw the overlay.
14+
*/
15+
export declare function calculate_split(col: number, row: number, panel: Layout, slot: string, drop_target: LayoutPath): LayoutPath;

dist/common/flatten.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { Layout } from "./layout_config.ts";
2+
/**
3+
* Flattens the layout tree by merging parent and child split panels that have
4+
* the same orientation and type.
5+
*
6+
* When a split panel contains a child split panel with the same orientation,
7+
* they are merged into a single split panel. The sizes array is scaled
8+
* correctly to maintain proportions.
9+
*
10+
* @param layout - The layout tree to flatten
11+
* @returns A new flattened layout tree (original is not mutated).
12+
*/
13+
export declare function flatten(layout: Layout): Layout;

dist/common/generate_grid.d.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { type Layout } from "./layout_config.ts";
2+
/**
3+
* Generates CSS Grid styles to render a layout tree.
4+
* Creates grid-template-rows, grid-template-columns, and positioning rules for
5+
* all child panels.
6+
*
7+
* @param layout - The layout tree to convert to CSS
8+
* @param round - If true, rounds percentages to whole numbers. Useful for
9+
* avoiding sub-pixel rendering issues. Defaults to false.
10+
* @returns CSS string containing :host and ::slotted rules implementing the
11+
* layout.
12+
*
13+
* @example
14+
* ```typescript
15+
* const layout = {
16+
* type: "split-panel",
17+
* orientation: "horizontal",
18+
* children: [
19+
* { type: "child-panel", child: "sidebar" },
20+
* { type: "child-panel", child: "main" }
21+
* ],
22+
* sizes: [0.25, 0.75]
23+
* };
24+
*
25+
* const css = create_css_grid_layout(layout);
26+
* // Returns CSS like:
27+
* // :host { display: grid; grid-template-columns: 25% 75%; ... }
28+
* // :host ::slotted([slot=sidebar]) { grid-column: 1; grid-row: 1; }
29+
* // :host ::slotted([slot=main]) { grid-column: 2; grid-row: 1; }
30+
* ```
31+
*/
32+
export declare function create_css_grid_layout(layout: Layout, round?: boolean, overlay?: [string, string]): string;

dist/common/generate_overlay.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import type { LayoutPath } from "./layout_config";
2+
export declare function updateOverlaySheet({ view_window: { row_start, row_end, col_start, col_end }, box, }: LayoutPath<DOMRect>): string;

dist/common/insert_child.d.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { Layout } from "./layout_config.ts";
2+
/**
3+
* Inserts a new child panel into the layout tree at a specified location.
4+
* Creates a split panel if necessary and redistributes sizes equally among all
5+
* children.
6+
*
7+
* @param panel - The root layout tree to insert into
8+
* @param child - Unique identifier for the new child panel
9+
* @param path - Array of indices defining where to insert. Empty array inserts
10+
* at root level.
11+
* @param orientation - Orientation for newly created split panels. Defaults to
12+
* "horizontal".
13+
* @returns A new layout tree with the child inserted (original is not mutated).
14+
*/
15+
export declare function insert_child(panel: Layout, child: string, path: number[], orientation?: "horizontal" | "vertical", is_edge?: boolean): Layout;

dist/common/layout_config.d.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* The percentage of the maximum resize distance that will be clamped.
3+
*
4+
*/
5+
export declare const MINIMUM_REDISTRIBUTION_SIZE_THRESHOLD = 0.15;
6+
/**
7+
* Threshold from panel edge that is considered a split vs drop action.
8+
*/
9+
export declare const SPLIT_EDGE_TOLERANCE = 0.25;
10+
/**
11+
* Tolerance threshold for considering two grid track positions as identical.
12+
*
13+
* When collecting and deduplicating track positions, any positions closer than
14+
* this value are treated as the same position to avoid redundant grid tracks.
15+
*/
16+
export declare const GRID_TRACK_COLLAPSE_TOLERANCE = 0.001;
17+
/**
18+
* The overlay default behavior.
19+
*/
20+
export declare const OVERLAY_DEFAULT: OverlayMode;
21+
/**
22+
* The overlay behavior type.
23+
*/
24+
export type OverlayMode = "grid" | "absolute" | "interactive";
25+
/**
26+
* The representation of a CSS grid, in JSON form.
27+
*/
28+
export type Layout = SplitLayout | TabLayout;
29+
/**
30+
* The orientation (of a `SplitPanel`).
31+
*/
32+
export type Orientation = "horizontal" | "vertical";
33+
/**
34+
* A logical rectange in percent-coordinates (of a (1, 1) square).
35+
*/
36+
export interface ViewWindow {
37+
row_start: number;
38+
row_end: number;
39+
col_start: number;
40+
col_end: number;
41+
}
42+
/**
43+
* A split panel that divides space among multiple child layouts
44+
* .
45+
* Child panels are arranged either horizontally (side by side) or vertically
46+
* (stacked), via the `orientation` property `"horizzontal"` and `"vertical"`
47+
* (respectively).
48+
*/
49+
export interface SplitLayout {
50+
type: "split-panel";
51+
children: Layout[];
52+
sizes: number[];
53+
orientation: Orientation;
54+
}
55+
/**
56+
* A leaf panel node that contains a single named child element.
57+
*/
58+
export interface TabLayout {
59+
type: "child-panel";
60+
child: string[];
61+
selected?: number;
62+
}
63+
/**
64+
* Represents a draggable divider between two panels in the layout.
65+
*
66+
* Used for hit detection.
67+
*/
68+
export interface LayoutDivider {
69+
path: number[];
70+
view_window: ViewWindow;
71+
type: Orientation;
72+
}
73+
/**
74+
* Represents a panel location result from hit detection.
75+
*
76+
* Contains both the panel identifier and its grid position in relative units.
77+
* The generic parameter `T` allows DOM-only properties (e.g. `DOMRect`) to be
78+
* shared in this cross-platform module.
79+
*/
80+
export interface LayoutPath<T = undefined> {
81+
type: "layout-path";
82+
slot: string;
83+
panel: TabLayout;
84+
path: number[];
85+
view_window: ViewWindow;
86+
column_offset: number;
87+
row_offset: number;
88+
orientation: Orientation;
89+
is_edge: boolean;
90+
box: T;
91+
}
92+
/**
93+
* Recursively iterates over all child panel names in the layout tree, yielding
94+
* panel names in depth-first order.
95+
*
96+
* @param panel - The layout tree to iterate over
97+
* @returns Generator yielding child panel names
98+
*/
99+
export declare function iter_panel_children(panel: Layout): Generator<string>;
100+
/**
101+
* An empty `Layout` with no panels.
102+
*/
103+
export declare const EMPTY_PANEL: Layout;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { type Layout } from "./layout_config.ts";
2+
/**
3+
* Adjusts panel sizes during a drag operation on a divider.
4+
*
5+
* The `delta` is distributed proportionally among affected panels, maintaining
6+
* the sum:
7+
*
8+
* - Panels before and including the path index shrink by delta.
9+
* - Panels after the path index grow by delta.
10+
*
11+
* @param panel - The root layout tree to modify.
12+
* @param path - Path to the divider being dragged (identifies which split panel
13+
* to resize).
14+
* @param delta - Amount to resize, as a fraction (0-1). Positive values grow
15+
* panels before the divider, negative values shrink them.
16+
* @returns A new layout tree with updated sizes (original is not mutated).
17+
* ```
18+
*/
19+
export declare function redistribute_panel_sizes(panel: Layout, path: number[], delta: number): Layout;

dist/common/remove_child.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { Layout } from "./layout_config.ts";
2+
/**
3+
* Removes a child panel from the layout tree by its name.
4+
*
5+
* Redistributes the removed panel's space proportionally among remaining
6+
* siblings. Automatically collapses split panels when only one child remains.
7+
*
8+
* @param panel - The root layout tree to remove from.
9+
* @param child - Name of the child panel to remove.
10+
* @returns A new layout tree with the child removed (original is not mutated).
11+
* Returns `EMPTY_PANEL` if the last panel is removed.
12+
*/
13+
export declare function remove_child(panel: Layout, child: string): Layout;

dist/extensions.d.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { RegularLayout } from "./regular-layout.ts";
2+
import { RegularLayoutFrame } from "./regular-layout-frame.ts";
3+
import { Layout } from "./common/layout_config.ts";
4+
declare global {
5+
interface Document {
6+
createElement(tagName: "regular-layout", options?: ElementCreationOptions): RegularLayout;
7+
createElement(tagName: "regular-layout-frame", options?: ElementCreationOptions): RegularLayoutFrame;
8+
querySelector<E extends Element = Element>(selectors: string): E | null;
9+
querySelector(selectors: "regular-layout"): RegularLayout | null;
10+
querySelector(selectors: "regular-layout-frame"): RegularLayoutFrame | null;
11+
}
12+
interface CustomElementRegistry {
13+
get(tagName: "regular-layout"): typeof RegularLayout;
14+
get(tagName: "regular-layout-frame"): typeof RegularLayoutFrame;
15+
}
16+
interface HTMLElement {
17+
addEventListener(name: "regular-layout-update", cb: (e: RegularLayoutEvent) => void, options?: {
18+
signal: AbortSignal;
19+
}): void;
20+
removeEventListener(name: "regular-layout-update", cb: any): void;
21+
}
22+
}
23+
export interface RegularLayoutEvent extends CustomEvent {
24+
detail: Layout;
25+
}
26+
export interface PerspectiveViewerElementExt {
27+
addEventListener(name: "regular-layout-update", cb: (e: RegularLayoutEvent) => void, options?: {
28+
signal: AbortSignal;
29+
}): void;
30+
removeEventListener(name: "regular-layout-update", cb: any): void;
31+
}

0 commit comments

Comments
 (0)