kopia lustrzana https://github.com/shoelace-style/shoelace
all except min/max
rodzic
a5b7f8fd6b
commit
a3ef96a799
|
@ -137,21 +137,6 @@ When the host element is resized, the fixed panel will maintain its size and the
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Minimum and Maximum Sizes
|
|
||||||
|
|
||||||
To set a minimum or maximum size of each panel, use the `--start-min`, `--start-max`, `--end-min`, and `--end-max` custom properties.
|
|
||||||
|
|
||||||
```html preview
|
|
||||||
<sl-split-panel style="--end-min: 25%; --end-max: 75%;">
|
|
||||||
<div slot="start">
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat, suscipit animi. Exercitationem, modi tenetur, voluptatibus magnam qui excepturi quasi autem et odit, recusandae obcaecati! Quaerat possimus facilis tempora consequatur officia?
|
|
||||||
</div>
|
|
||||||
<div slot="end">
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat, suscipit animi. Exercitationem, modi tenetur, voluptatibus magnam qui excepturi quasi autem et odit, recusandae obcaecati! Quaerat possimus facilis tempora consequatur officia?
|
|
||||||
</div>
|
|
||||||
</sl-split-panel>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Nested Split Panels
|
### Nested Split Panels
|
||||||
|
|
||||||
Create complex layouts that can be resized independently by nesting split panels.
|
Create complex layouts that can be resized independently by nesting split panels.
|
||||||
|
@ -179,7 +164,40 @@ Create complex layouts that can be resized independently by nesting split panels
|
||||||
You can target the `divider` part to apply CSS properties to the divider. Optionally, you can slot an element into the `handle` slot to show a handle.
|
You can target the `divider` part to apply CSS properties to the divider. Optionally, you can slot an element into the `handle` slot to show a handle.
|
||||||
|
|
||||||
```html preview
|
```html preview
|
||||||
TODO
|
<div class="split-panel-custom-divider">
|
||||||
|
<sl-split-panel>
|
||||||
|
<sl-icon slot="handle" name="grip-vertical"></sl-icon>
|
||||||
|
<div slot="start">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat, suscipit animi. Exercitationem, modi tenetur, voluptatibus magnam qui excepturi quasi autem et odit, recusandae obcaecati! Quaerat possimus facilis tempora consequatur officia?
|
||||||
|
</div>
|
||||||
|
<div slot="end">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat, suscipit animi. Exercitationem, modi tenetur, voluptatibus magnam qui excepturi quasi autem et odit, recusandae obcaecati! Quaerat possimus facilis tempora consequatur officia?
|
||||||
|
</div>
|
||||||
|
</sl-split-panel>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.split-panel-custom-divider sl-split-panel::part(divider) {
|
||||||
|
background-color: var(--sl-color-pink-600);
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-panel-custom-divider sl-icon {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: var(--sl-border-radius-small);
|
||||||
|
background: var(--sl-color-pink-600);
|
||||||
|
color: var(--sl-color-neutral-0);
|
||||||
|
padding: .5rem .125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-panel-custom-divider sl-split-panel::part(divider):focus-visible {
|
||||||
|
background-color: var(--sl-color-primary-600);
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-panel-custom-divider sl-split-panel:focus-within sl-icon {
|
||||||
|
background-color: var(--sl-color-primary-600);
|
||||||
|
color: var(--sl-color-neutral-0);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
```
|
```
|
||||||
|
|
||||||
[component-metadata:sl-split-panel]
|
[component-metadata:sl-split-panel]
|
||||||
|
|
|
@ -8,10 +8,6 @@ export default css`
|
||||||
:host {
|
:host {
|
||||||
--divider-width: 4px;
|
--divider-width: 4px;
|
||||||
--divider-hit-area: 12px;
|
--divider-hit-area: 12px;
|
||||||
--start-min: 0%;
|
|
||||||
--start-max: 100%;
|
|
||||||
--end-min: 0%;
|
|
||||||
--end-max: 100%;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
@ -30,8 +26,11 @@ export default css`
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
position: relative;
|
|
||||||
flex: 0 0 var(--divider-width);
|
flex: 0 0 var(--divider-width);
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
background-color: var(--sl-color-neutral-200);
|
background-color: var(--sl-color-neutral-200);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
@ -49,14 +48,9 @@ export default css`
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Horizontal */
|
/* Horizontal */
|
||||||
:host(:not([vertical])) .start {
|
:host(:not([vertical])) .start,
|
||||||
min-width: var(--start-min);
|
|
||||||
max-width: var(--start-max);
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(:not([vertical])) .end {
|
:host(:not([vertical])) .end {
|
||||||
min-width: var(--end-min);
|
max-width: 100%;
|
||||||
max-width: var(--end-max);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(:not([vertical], [disabled])) .divider {
|
:host(:not([vertical], [disabled])) .divider {
|
||||||
|
@ -64,6 +58,7 @@ export default css`
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(:not([vertical])) .divider::after {
|
:host(:not([vertical])) .divider::after {
|
||||||
|
display: flex;
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -76,14 +71,9 @@ export default css`
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([vertical]) .start {
|
:host([vertical]) .start,
|
||||||
min-height: var(--start-min);
|
|
||||||
max-height: var(--start-max);
|
|
||||||
}
|
|
||||||
|
|
||||||
:host([vertical]) .end {
|
:host([vertical]) .end {
|
||||||
min-height: var(--end-min);
|
max-height: 100%;
|
||||||
max-height: var(--end-max);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:host([vertical]:not([disabled])) .divider {
|
:host([vertical]:not([disabled])) .divider {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { styleMap } from 'lit/directives/style-map.js';
|
||||||
import { clamp } from '../../internal/math';
|
import { clamp } from '../../internal/math';
|
||||||
import { emit } from '../../internal/event';
|
import { emit } from '../../internal/event';
|
||||||
import { watch } from '../../internal/watch';
|
import { watch } from '../../internal/watch';
|
||||||
|
import { LocalizeController } from '../../utilities/localize';
|
||||||
import styles from './split-panel.styles';
|
import styles from './split-panel.styles';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,8 +15,11 @@ import styles from './split-panel.styles';
|
||||||
* @event sl-reposition - Emitted when the divider is repositioned.
|
* @event sl-reposition - Emitted when the divider is repositioned.
|
||||||
* @event {{ entries: ResizeObserverEntry[] }} sl-resize - Emitted when the container is resized.
|
* @event {{ entries: ResizeObserverEntry[] }} sl-resize - Emitted when the container is resized.
|
||||||
*
|
*
|
||||||
|
* @csspart divider - The divider that separates the start and end panels.
|
||||||
|
*
|
||||||
* @slot start - The start panel.
|
* @slot start - The start panel.
|
||||||
* @slot end - The end panel.
|
* @slot end - The end panel.
|
||||||
|
* @slot handle - An optional handle to render at the center of the divider.
|
||||||
*
|
*
|
||||||
* @cssproperty [--divider-width=4px] - The width of the visible divider.
|
* @cssproperty [--divider-width=4px] - The width of the visible divider.
|
||||||
* @cssproperty [--divider-hit-area=12px] - The invisible area around the divider where dragging can occur.
|
* @cssproperty [--divider-hit-area=12px] - The invisible area around the divider where dragging can occur.
|
||||||
|
@ -24,6 +28,7 @@ import styles from './split-panel.styles';
|
||||||
export default class SlSplitPanel extends LitElement {
|
export default class SlSplitPanel extends LitElement {
|
||||||
static styles = styles;
|
static styles = styles;
|
||||||
|
|
||||||
|
private localize = new LocalizeController(this);
|
||||||
private resizeObserver: ResizeObserver;
|
private resizeObserver: ResizeObserver;
|
||||||
private size: number;
|
private size: number;
|
||||||
|
|
||||||
|
@ -75,20 +80,46 @@ export default class SlSplitPanel extends LitElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDrag(event: MouseEvent | TouchEvent) {
|
handleDrag(event: Event) {
|
||||||
const isMouseEvent = event instanceof MouseEvent;
|
if (this.disabled) {
|
||||||
const originalX = isMouseEvent ? event.pageX : event.changedTouches[0].pageX;
|
return;
|
||||||
const originalY = isMouseEvent ? event.pageY : event.changedTouches[0].pageY;
|
}
|
||||||
const original = this.vertical ? originalY : originalX;
|
|
||||||
const originalPosition = Number(this.position);
|
|
||||||
|
|
||||||
const move = (event: MouseEvent | TouchEvent) => {
|
// Prevent text selection when dragging
|
||||||
const isMouseEvent = event instanceof MouseEvent;
|
event.preventDefault();
|
||||||
const currentX = isMouseEvent ? event.pageX : event.changedTouches[0].pageX;
|
|
||||||
const currentY = isMouseEvent ? event.pageY : event.changedTouches[0].pageY;
|
function drag(container: HTMLElement, onMove: (x: number, y: number) => void) {
|
||||||
const current = this.vertical ? currentY : currentX;
|
const move = (event: any) => {
|
||||||
let delta = this.fixed === 'end' ? original - current : current - original;
|
const dims = container.getBoundingClientRect();
|
||||||
let newPosition = originalPosition + delta;
|
const defaultView = container.ownerDocument.defaultView!;
|
||||||
|
const offsetX = dims.left + defaultView.pageXOffset;
|
||||||
|
const offsetY = dims.top + defaultView.pageYOffset;
|
||||||
|
const x = (event.changedTouches ? event.changedTouches[0].pageX : event.pageX) - offsetX;
|
||||||
|
const y = (event.changedTouches ? event.changedTouches[0].pageY : event.pageY) - offsetY;
|
||||||
|
|
||||||
|
onMove(x, y);
|
||||||
|
};
|
||||||
|
|
||||||
|
const stop = () => {
|
||||||
|
document.removeEventListener('mousemove', move);
|
||||||
|
document.removeEventListener('touchmove', move);
|
||||||
|
document.removeEventListener('mouseup', stop);
|
||||||
|
document.removeEventListener('touchend', stop);
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', move, { passive: true });
|
||||||
|
document.addEventListener('touchmove', move, { passive: true });
|
||||||
|
document.addEventListener('mouseup', stop);
|
||||||
|
document.addEventListener('touchend', stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
drag(this, (x, y) => {
|
||||||
|
let newPosition = this.vertical ? y : x;
|
||||||
|
|
||||||
|
// Flip for end panels
|
||||||
|
if (this.fixed === 'end') {
|
||||||
|
newPosition = this.size - newPosition;
|
||||||
|
}
|
||||||
|
|
||||||
// Check snap points
|
// Check snap points
|
||||||
if (this.snap) {
|
if (this.snap) {
|
||||||
|
@ -110,24 +141,7 @@ export default class SlSplitPanel extends LitElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.position = clamp(newPosition, 0, this.size);
|
this.position = clamp(newPosition, 0, this.size);
|
||||||
};
|
});
|
||||||
|
|
||||||
const stop = () => {
|
|
||||||
document.removeEventListener('mousemove', move);
|
|
||||||
document.removeEventListener('touchmove', move);
|
|
||||||
document.removeEventListener('mouseup', stop);
|
|
||||||
document.removeEventListener('touchend', stop);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!this.disabled) {
|
|
||||||
document.addEventListener('mousemove', move);
|
|
||||||
document.addEventListener('touchmove', move);
|
|
||||||
document.addEventListener('mouseup', stop);
|
|
||||||
document.addEventListener('touchend', stop);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent text selection
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown(event: KeyboardEvent) {
|
handleKeyDown(event: KeyboardEvent) {
|
||||||
|
@ -197,11 +211,11 @@ export default class SlSplitPanel extends LitElement {
|
||||||
// TODO - custom divider styles + handle
|
// TODO - custom divider styles + handle
|
||||||
|
|
||||||
if (this.fixed === 'end') {
|
if (this.fixed === 'end') {
|
||||||
start = `1 1 0%`;
|
start = `1 1 auto`;
|
||||||
end = `0 0 calc((${this.position}px - var(--divider-width) / 2)`;
|
end = `0 0 calc((${this.position}px - var(--divider-width) / 2)`;
|
||||||
} else {
|
} else {
|
||||||
start = `0 0 calc(${this.position}px - var(--divider-width) / 2)`;
|
start = `0 0 calc(${this.position}px - var(--divider-width) / 2)`;
|
||||||
end = `1 1 0%`;
|
end = `1 1 auto`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
|
@ -215,12 +229,17 @@ export default class SlSplitPanel extends LitElement {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
part="divider"
|
||||||
class="divider"
|
class="divider"
|
||||||
tabindex=${ifDefined(this.disabled ? undefined : '0')}
|
tabindex=${ifDefined(this.disabled ? undefined : '0')}
|
||||||
|
role="separator"
|
||||||
|
aria-label=${this.localize.term('drag_to_resize')}
|
||||||
@keydown=${this.handleKeyDown}
|
@keydown=${this.handleKeyDown}
|
||||||
@mousedown=${this.handleDrag}
|
@mousedown=${this.handleDrag}
|
||||||
@touchstart=${this.handleDrag}
|
@touchstart=${this.handleDrag}
|
||||||
></div>
|
>
|
||||||
|
<slot name="handle"></slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="end"
|
class="end"
|
||||||
|
|
|
@ -8,6 +8,7 @@ const translation: Translation = {
|
||||||
|
|
||||||
close: 'Close',
|
close: 'Close',
|
||||||
copy: 'Copy',
|
copy: 'Copy',
|
||||||
|
drag_to_resize: 'Drag to resize',
|
||||||
progress: 'Progress',
|
progress: 'Progress',
|
||||||
scroll_to_end: 'Scroll to end',
|
scroll_to_end: 'Scroll to end',
|
||||||
scroll_to_start: 'Scroll to start',
|
scroll_to_start: 'Scroll to start',
|
||||||
|
|
|
@ -8,6 +8,7 @@ const translation: Translation = {
|
||||||
|
|
||||||
close: 'Cerrar',
|
close: 'Cerrar',
|
||||||
copy: 'Copiar',
|
copy: 'Copiar',
|
||||||
|
drag_to_resize: 'Arrastra para cambiar el tamaño',
|
||||||
progress: 'Progreso',
|
progress: 'Progreso',
|
||||||
scroll_to_end: 'Desplazarse hasta el final',
|
scroll_to_end: 'Desplazarse hasta el final',
|
||||||
scroll_to_start: 'Desplazarse al inicio',
|
scroll_to_start: 'Desplazarse al inicio',
|
||||||
|
|
Ładowanie…
Reference in New Issue