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>
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
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.
|
||||
|
||||
```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]
|
||||
|
|
|
@ -8,10 +8,6 @@ export default css`
|
|||
:host {
|
||||
--divider-width: 4px;
|
||||
--divider-hit-area: 12px;
|
||||
--start-min: 0%;
|
||||
--start-max: 100%;
|
||||
--end-min: 0%;
|
||||
--end-max: 100%;
|
||||
|
||||
display: flex;
|
||||
}
|
||||
|
@ -30,8 +26,11 @@ export default css`
|
|||
}
|
||||
|
||||
.divider {
|
||||
position: relative;
|
||||
flex: 0 0 var(--divider-width);
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--sl-color-neutral-200);
|
||||
z-index: 1;
|
||||
}
|
||||
|
@ -49,14 +48,9 @@ export default css`
|
|||
}
|
||||
|
||||
/* Horizontal */
|
||||
:host(:not([vertical])) .start {
|
||||
min-width: var(--start-min);
|
||||
max-width: var(--start-max);
|
||||
}
|
||||
|
||||
:host(:not([vertical])) .start,
|
||||
:host(:not([vertical])) .end {
|
||||
min-width: var(--end-min);
|
||||
max-width: var(--end-max);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
:host(:not([vertical], [disabled])) .divider {
|
||||
|
@ -64,6 +58,7 @@ export default css`
|
|||
}
|
||||
|
||||
:host(:not([vertical])) .divider::after {
|
||||
display: flex;
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
|
@ -76,14 +71,9 @@ export default css`
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
:host([vertical]) .start {
|
||||
min-height: var(--start-min);
|
||||
max-height: var(--start-max);
|
||||
}
|
||||
|
||||
:host([vertical]) .start,
|
||||
:host([vertical]) .end {
|
||||
min-height: var(--end-min);
|
||||
max-height: var(--end-max);
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
:host([vertical]:not([disabled])) .divider {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { styleMap } from 'lit/directives/style-map.js';
|
|||
import { clamp } from '../../internal/math';
|
||||
import { emit } from '../../internal/event';
|
||||
import { watch } from '../../internal/watch';
|
||||
import { LocalizeController } from '../../utilities/localize';
|
||||
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 {{ 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 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-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 {
|
||||
static styles = styles;
|
||||
|
||||
private localize = new LocalizeController(this);
|
||||
private resizeObserver: ResizeObserver;
|
||||
private size: number;
|
||||
|
||||
|
@ -75,20 +80,46 @@ export default class SlSplitPanel extends LitElement {
|
|||
}
|
||||
}
|
||||
|
||||
handleDrag(event: MouseEvent | TouchEvent) {
|
||||
const isMouseEvent = event instanceof MouseEvent;
|
||||
const originalX = isMouseEvent ? event.pageX : event.changedTouches[0].pageX;
|
||||
const originalY = isMouseEvent ? event.pageY : event.changedTouches[0].pageY;
|
||||
const original = this.vertical ? originalY : originalX;
|
||||
const originalPosition = Number(this.position);
|
||||
handleDrag(event: Event) {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const move = (event: MouseEvent | TouchEvent) => {
|
||||
const isMouseEvent = event instanceof MouseEvent;
|
||||
const currentX = isMouseEvent ? event.pageX : event.changedTouches[0].pageX;
|
||||
const currentY = isMouseEvent ? event.pageY : event.changedTouches[0].pageY;
|
||||
const current = this.vertical ? currentY : currentX;
|
||||
let delta = this.fixed === 'end' ? original - current : current - original;
|
||||
let newPosition = originalPosition + delta;
|
||||
// Prevent text selection when dragging
|
||||
event.preventDefault();
|
||||
|
||||
function drag(container: HTMLElement, onMove: (x: number, y: number) => void) {
|
||||
const move = (event: any) => {
|
||||
const dims = container.getBoundingClientRect();
|
||||
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
|
||||
if (this.snap) {
|
||||
|
@ -110,24 +141,7 @@ export default class SlSplitPanel extends LitElement {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -197,11 +211,11 @@ export default class SlSplitPanel extends LitElement {
|
|||
// TODO - custom divider styles + handle
|
||||
|
||||
if (this.fixed === 'end') {
|
||||
start = `1 1 0%`;
|
||||
start = `1 1 auto`;
|
||||
end = `0 0 calc((${this.position}px - var(--divider-width) / 2)`;
|
||||
} else {
|
||||
start = `0 0 calc(${this.position}px - var(--divider-width) / 2)`;
|
||||
end = `1 1 0%`;
|
||||
end = `1 1 auto`;
|
||||
}
|
||||
|
||||
return html`
|
||||
|
@ -215,12 +229,17 @@ export default class SlSplitPanel extends LitElement {
|
|||
</div>
|
||||
|
||||
<div
|
||||
part="divider"
|
||||
class="divider"
|
||||
tabindex=${ifDefined(this.disabled ? undefined : '0')}
|
||||
role="separator"
|
||||
aria-label=${this.localize.term('drag_to_resize')}
|
||||
@keydown=${this.handleKeyDown}
|
||||
@mousedown=${this.handleDrag}
|
||||
@touchstart=${this.handleDrag}
|
||||
></div>
|
||||
>
|
||||
<slot name="handle"></slot>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="end"
|
||||
|
|
|
@ -8,6 +8,7 @@ const translation: Translation = {
|
|||
|
||||
close: 'Close',
|
||||
copy: 'Copy',
|
||||
drag_to_resize: 'Drag to resize',
|
||||
progress: 'Progress',
|
||||
scroll_to_end: 'Scroll to end',
|
||||
scroll_to_start: 'Scroll to start',
|
||||
|
|
|
@ -8,6 +8,7 @@ const translation: Translation = {
|
|||
|
||||
close: 'Cerrar',
|
||||
copy: 'Copiar',
|
||||
drag_to_resize: 'Arrastra para cambiar el tamaño',
|
||||
progress: 'Progreso',
|
||||
scroll_to_end: 'Desplazarse hasta el final',
|
||||
scroll_to_start: 'Desplazarse al inicio',
|
||||
|
|
Ładowanie…
Reference in New Issue