browsertrix/frontend/src/components/numbered-list.ts

159 lines
3.6 KiB
TypeScript

/**
* Styled numbered list
*
* Usage example:
* ```ts
* <btrix-numbered-list>
* <btrix-numbered-list-item>
* <span slot="marker">1.</span> Content
* </btrix-numbered-list-item>
* </btrix-numbered-list>
* ```
*/
import { LitElement, html, css } from "lit";
import { property, queryAssignedElements } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
export class NumberedListItem extends LitElement {
@property({ type: Boolean })
isFirst: boolean = false;
@property({ type: Boolean })
isLast: boolean = false;
@property({ type: Boolean })
isEven: boolean = false;
static styles = css`
:host,
.item {
display: contents;
}
.content {
border-left: var(--sl-panel-border-width) solid
var(--sl-panel-border-color);
border-right: var(--sl-panel-border-width) solid
var(--sl-panel-border-color);
padding: var(--sl-spacing-2x-small) var(--sl-spacing-x-small);
line-height: 1;
min-height: var(--item-height);
box-sizing: border-box;
}
.marker {
color: var(--sl-color-neutral-400);
line-height: 1;
font-size: var(--sl-font-size-medium);
font-weight: var(--sl-font-weight-normal);
text-align: right;
white-space: nowrap;
}
.item.first .content {
border-top: var(--sl-panel-border-width) solid
var(--sl-panel-border-color);
border-top-left-radius: var(--sl-border-radius-medium);
border-top-right-radius: var(--sl-border-radius-medium);
}
.item.last .content {
border-bottom: var(--sl-panel-border-width) solid
var(--sl-panel-border-color);
border-bottom-left-radius: var(--sl-border-radius-medium);
border-bottom-right-radius: var(--sl-border-radius-medium);
}
.item.even .content {
background-color: var(--sl-color-neutral-50); */
}
`;
render() {
return html`
<div
class=${classMap({
item: true,
first: this.isFirst,
last: this.isLast,
even: this.isEven,
})}
>
<div class="marker"><slot name="marker"></slot></div>
<div class="content"><slot></slot></div>
</div>
`;
}
}
export class NumberedListHeader extends LitElement {
static styles = css`
:host,
header {
display: contents;
}
.content {
grid-column: 2 / -1;
padding-bottom: var(--sl-spacing-x-small);
color: var(--sl-color-neutral-600);
font-size: var(--sl-font-size-x-small);
line-height: 1rem;
}
`;
render() {
return html`<header>
<div class="content"><slot></slot></div>
</header>`;
}
}
export class NumberedList extends LitElement {
static styles = css`
:host {
display: block;
}
.list {
display: grid;
grid-template-columns: max-content 1fr;
grid-column-gap: var(--sl-spacing-x-small);
align-items: center;
}
ol {
display: contents;
font-family: var(--sl-font-mono);
list-style-type: none;
margin: 0;
padding: 0;
}
`;
@queryAssignedElements({ selector: "btrix-numbered-list-item" })
listItems!: NumberedListItem[];
render() {
return html`
<div class="list">
<slot name="header"></slot>
<ol>
<slot @slotchange=${this.handleSlotchange}></slot>
</ol>
</div>
`;
}
private handleSlotchange() {
this.listItems.forEach((el, i) => {
if (!el.attributes.getNamedItem("role")) {
el.setAttribute("role", "listitem");
}
el.isFirst = i === 0;
el.isLast = i === this.listItems.length - 1;
el.isEven = i % 2 !== 0;
});
}
}