import { css, html } from "lit";
import { BaseElement } from "../../core/base-element.ts";
/**
* @component ct-resizable-panel
* @description Individual resizable panel component that works within a resizable panel group
*
* @tag ct-resizable-panel
*
* @attribute {number} default-size - Default size of the panel as a percentage (0-100). Defaults to 50.
* @attribute {number} min-size - Minimum size of the panel as a percentage (0-100). Defaults to 0.
* @attribute {number} max-size - Maximum size of the panel as a percentage (0-100). Defaults to 100.
* @attribute {boolean} collapsible - Whether the panel can be collapsed to zero size
*
* @slot default - Content of the resizable panel
*
* @csspart panel - The panel container element
*
* @example
* ```html
*
*
*
*
Sidebar content
*
*
*
*
Main content
*
*
*
*
*
*
*
Top panel
*
*
*
*
Bottom panel (collapsible)
*
*
*
*
*
*
Constrained panel
*
* ```
*
* @note
* - Must be used within a ct-resizable-panel-group
* - Panels are separated by ct-resizable-handle components
* - Size values are percentages of the total available space
* - The component automatically validates that min <= default <= max
*/
export class CTResizablePanel extends BaseElement {
static override properties = {
minSize: { type: Number, attribute: "min-size" },
defaultSize: { type: Number, attribute: "default-size" },
maxSize: { type: Number, attribute: "max-size" },
collapsible: { type: Boolean },
};
declare minSize: number;
declare defaultSize: number;
declare maxSize: number;
declare collapsible: boolean;
static override styles = css`
:host {
display: block;
overflow: auto;
position: relative;
}
.panel {
width: 100%;
height: 100%;
position: relative;
}
/* Ensure content respects panel bounds */
.panel > ::slotted(*) {
max-width: 100%;
max-height: 100%;
}
`;
constructor() {
super();
this.minSize = 0;
this.defaultSize = 50;
this.maxSize = 100;
this.collapsible = false;
}
override connectedCallback() {
super.connectedCallback();
this.validateSizes();
}
override updated(changedProperties: Map) {
super.updated(changedProperties);
if (
changedProperties.has("minSize") ||
changedProperties.has("defaultSize") ||
changedProperties.has("maxSize")
) {
this.validateSizes();
}
}
override render() {
return html`
`;
}
private validateSizes(): void {
// Ensure values are within valid range
this.minSize = Math.max(0, Math.min(100, this.minSize));
this.maxSize = Math.max(0, Math.min(100, this.maxSize));
this.defaultSize = Math.max(0, Math.min(100, this.defaultSize));
// Ensure min <= default <= max
if (this.minSize > this.maxSize) {
const temp = this.minSize;
this.minSize = this.maxSize;
this.maxSize = temp;
}
if (this.defaultSize < this.minSize) {
this.defaultSize = this.minSize;
} else if (this.defaultSize > this.maxSize) {
this.defaultSize = this.maxSize;
}
// If collapsible, ensure minSize is 0
if (this.collapsible) {
this.minSize = 0;
}
}
}
globalThis.customElements.define("ct-resizable-panel", CTResizablePanel);