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
114 changes: 114 additions & 0 deletions dev/vscode-split-layout/csp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
content="
default-src 'none';
script-src 'nonce-abc123';
script-src-elem 'nonce-abc123';
font-src 'self' 'nonce-abc123' data:;
img-src data:;
style-src 'nonce-abc123';
style-src-elem 'nonce-abc123'"
/>
<title>VSCode Elements</title>
<link
rel="stylesheet"
href="/node_modules/@vscode/codicons/dist/codicon.css"
id="vscode-codicon-stylesheet"
nonce="abc123"
/>
<style nonce="abc123">
vscode-split-layout {
width: 500px;
height: 250px;
}

vscode-scrollable {
height: 100%;
width: 100%;
}
</style>
<script nonce="abc123">
window.vscodeWebviewPlaygroundNonce = 'abc123';
</script>
<script
type="module"
src="/node_modules/@vscode-elements/webview-playground/dist/index.js"
nonce="abc123"
></script>
<script type="module" src="/dist/main.js" nonce="abc123"></script>
<script nonce="abc123">
const logEvents = (selector, eventType) => {
document.querySelector(selector).addEventListener(eventType, (ev) => {
console.log(ev);
});
};
</script>
</head>

<body>
<h1>Apply CSP</h1>
<main>
<vscode-demo>
<vscode-split-layout>
<div slot="start" class="split-layout-content start">
<vscode-scrollable>
Praesent ultrices mauris lectus, eu molestie erat lacinia vitae.
Phasellus vestibulum pellentesque ligula malesuada sollicitudin.
Vivamus vitae erat eget nulla laoreet porttitor. Nullam sit amet leo
et velit molestie maximus. Vestibulum arcu leo, tempor nec pretium
id, vehicula id odio. Etiam ultricies ligula dolor, in tincidunt
nunc maximus at. Curabitur tincidunt nulla in magna pharetra
commodo. Donec vestibulum mollis quam, ut consequat dolor finibus
ac. Nulla suscipit ac sem non fringilla. Nullam eros ante, suscipit
hendrerit molestie a, tempor nec turpis. Morbi eget erat suscipit,
blandit nibh nec, molestie augue. Aenean consectetur dapibus mauris,
eget ultricies sapien porttitor nec. Praesent ultrices mauris
lectus, eu molestie erat lacinia vitae. Phasellus vestibulum
pellentesque ligula malesuada sollicitudin. Vivamus vitae erat eget
nulla laoreet porttitor. Nullam sit amet leo et velit molestie
maximus. Vestibulum arcu leo, tempor nec pretium id, vehicula id
odio. Etiam ultricies ligula dolor, in tincidunt nunc maximus at.
Curabitur tincidunt nulla in magna pharetra commodo. Donec
vestibulum mollis quam, ut consequat dolor finibus ac. Nulla
suscipit ac sem non fringilla. Nullam eros ante, suscipit hendrerit
molestie a, tempor nec turpis. Morbi eget erat suscipit, blandit
nibh nec, molestie augue. Aenean consectetur dapibus mauris, eget
ultricies sapien porttitor nec.
</vscode-scrollable>
</div>
<div slot="end" class="split-layout-content">
<vscode-scrollable>
Praesent ultrices mauris lectus, eu molestie erat lacinia vitae.
Phasellus vestibulum pellentesque ligula malesuada sollicitudin.
Vivamus vitae erat eget nulla laoreet porttitor. Nullam sit amet leo
et velit molestie maximus. Vestibulum arcu leo, tempor nec pretium
id, vehicula id odio. Etiam ultricies ligula dolor, in tincidunt
nunc maximus at. Curabitur tincidunt nulla in magna pharetra
commodo. Donec vestibulum mollis quam, ut consequat dolor finibus
ac. Nulla suscipit ac sem non fringilla. Nullam eros ante, suscipit
hendrerit molestie a, tempor nec turpis. Morbi eget erat suscipit,
blandit nibh nec, molestie augue. Aenean consectetur dapibus mauris,
eget ultricies sapien porttitor nec. Praesent ultrices mauris
lectus, eu molestie erat lacinia vitae. Phasellus vestibulum
pellentesque ligula malesuada sollicitudin. Vivamus vitae erat eget
nulla laoreet porttitor. Nullam sit amet leo et velit molestie
maximus. Vestibulum arcu leo, tempor nec pretium id, vehicula id
odio. Etiam ultricies ligula dolor, in tincidunt nunc maximus at.
Curabitur tincidunt nulla in magna pharetra commodo. Donec
vestibulum mollis quam, ut consequat dolor finibus ac. Nulla
suscipit ac sem non fringilla. Nullam eros ante, suscipit hendrerit
molestie a, tempor nec turpis. Morbi eget erat suscipit, blandit
nibh nec, molestie augue. Aenean consectetur dapibus mauris, eget
ultricies sapien porttitor nec.
</vscode-scrollable>
</div>
</vscode-split-layout>
</vscode-demo>
</main>
</body>
</html>
128 changes: 80 additions & 48 deletions src/vscode-split-layout/vscode-split-layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
state,
} from 'lit/decorators.js';
import {classMap} from 'lit/directives/class-map.js';
import {styleMap} from 'lit/directives/style-map.js';
import {VscElement} from '../includes/VscElement.js';
import styles from './vscode-split-layout.styles.js';

Expand Down Expand Up @@ -144,7 +143,13 @@ export class VscodeSplitLayout extends VscElement {
@query('.wrapper')
private _wrapperEl!: HTMLDivElement;

@query('.handle')
@query('#start-pane', true)
private _startPaneEl!: HTMLDivElement;

@query('#end-pane', true)
private _endPaneEl!: HTMLDivElement;

@query('#handle', true)
private _handleEl!: HTMLDivElement;

@queryAssignedElements({slot: 'start', selector: 'vscode-split-layout'})
Expand All @@ -158,6 +163,7 @@ export class VscodeSplitLayout extends VscElement {
private _resizeObserver: ResizeObserver;
private _wrapperObserved: boolean = false;
private _fixedPaneSize: number = 0;
private _firstUpdated = false;

constructor() {
super();
Expand Down Expand Up @@ -191,7 +197,7 @@ export class VscodeSplitLayout extends VscElement {
super.connectedCallback();
}

protected firstUpdated(_changedProperties: PropertyValues): void {
protected firstUpdated(changedProperties: PropertyValues): void {
if (this.fixedPane !== 'none') {
this._resizeObserver.observe(this._wrapperEl);
this._wrapperObserved = true;
Expand All @@ -205,6 +211,74 @@ export class VscodeSplitLayout extends VscElement {

this._setPosition(value, unit);
this._initFixedPane();
this._updateInlineStyles(changedProperties);
this._firstUpdated = true;
}

protected willUpdate(changedProperties: PropertyValues): void {
if (this._firstUpdated) {
this._updateInlineStyles(changedProperties);
}
}

// Updating inline styles via the style property because using the style
// attribute is not CSP-compliant.
private _updateInlineStyles(changedProperties: PropertyValues) {
if (
changedProperties.has('_handlePosition') ||
changedProperties.has('split') ||
changedProperties.has('fixedPane') ||
changedProperties.has('handleSize')
) {
const {width, height} = this._boundRect;
const maxPos = this.split === 'vertical' ? width : height;
const startPaneFlexValue =
this.fixedPane === 'start'
? `0 0 ${this._fixedPaneSize}px`
: `1 1 ${pxToPercent(this._handlePosition, maxPos)}%`;
const endPaneFlexValue =
this.fixedPane === 'end'
? `0 0 ${this._fixedPaneSize}px`
: `1 1 ${pxToPercent(maxPos - this._handlePosition, maxPos)}%`;

if (this._startPaneEl) {
this._startPaneEl.style.flex = startPaneFlexValue;
}

if (this._endPaneEl) {
this._endPaneEl.style.flex = endPaneFlexValue;
}
}

if (changedProperties.has('split')) {
const handleSize = this.handleSize ?? DEFAULT_HANDLE_SIZE;

if (this.split === 'vertical') {
this._handleEl.style.marginLeft = `${0 - handleSize / 2}px`;
this._handleEl.style.marginTop = '0';
this._handleEl.style.width = `${handleSize}px`;
}

if (this.split === 'horizontal') {
this._handleEl.style.marginTop = `${0 - handleSize / 2}px`;
this._handleEl.style.marginLeft = '0';
this._handleEl.style.height = `${handleSize}px`;
}
}

if (changedProperties.has('_handlePosition')) {
const {width, height} = this._boundRect;
const maxPos = this.split === 'vertical' ? width : height;

const handlePosCss =
this.fixedPane !== 'none'
? `${this._handlePosition}px`
: `${pxToPercent(this._handlePosition, maxPos)}%`;

this._handleEl.style.left =
this.split === 'vertical' ? handlePosCss : '0';
this._handleEl.style.top = this.split === 'vertical' ? '0' : handlePosCss;
}
}

private _handlePositionPropChanged() {
Expand Down Expand Up @@ -374,48 +448,6 @@ export class VscodeSplitLayout extends VscElement {
}

render(): TemplateResult {
const {width, height} = this._boundRect;
const maxPos = this.split === 'vertical' ? width : height;
const handlePosCss =
this.fixedPane !== 'none'
? `${this._handlePosition}px`
: `${pxToPercent(this._handlePosition, maxPos)}%`;

let startPaneSize = '';

if (this.fixedPane === 'start') {
startPaneSize = `0 0 ${this._fixedPaneSize}px`;
} else {
startPaneSize = `1 1 ${pxToPercent(this._handlePosition, maxPos)}%`;
}

let endPaneSize = '';

if (this.fixedPane === 'end') {
endPaneSize = `0 0 ${this._fixedPaneSize}px`;
} else {
endPaneSize = `1 1 ${pxToPercent(maxPos - this._handlePosition, maxPos)}%`;
}

const handleStylesPropObj: {[prop: string]: string} = {
left: this.split === 'vertical' ? handlePosCss : '0',
top: this.split === 'vertical' ? '0' : handlePosCss,
};

const handleSize = this.handleSize ?? DEFAULT_HANDLE_SIZE;

if (this.split === 'vertical') {
handleStylesPropObj.marginLeft = `${0 - handleSize / 2}px`;
handleStylesPropObj.width = `${handleSize}px`;
}

if (this.split === 'horizontal') {
handleStylesPropObj.height = `${handleSize}px`;
handleStylesPropObj.marginTop = `${0 - handleSize / 2}px`;
}

const handleStyles = styleMap(handleStylesPropObj);

const handleOverlayClasses = classMap({
'handle-overlay': true,
active: this._isDragActive,
Expand All @@ -438,16 +470,16 @@ export class VscodeSplitLayout extends VscElement {

return html`
<div class=${classMap(wrapperClasses)}>
<div class="start" style=${styleMap({flex: startPaneSize})}>
<div class="start" id="start-pane">
<slot name="start" @slotchange=${this._handleSlotChange}></slot>
</div>
<div class="end" style=${styleMap({flex: endPaneSize})}>
<div class="end" id="end-pane">
<slot name="end" @slotchange=${this._handleSlotChange}></slot>
</div>
<div class=${handleOverlayClasses}></div>
<div
class=${handleClasses}
style=${handleStyles}
id="handle"
@mouseover=${this._handleMouseOver}
@mouseout=${this._handleMouseOut}
@mousedown=${this._handleMouseDown}
Expand Down