import { html, css, LitElement } from "lit"; import { customElement, property, query } from "lit/decorators.js"; import { LitElementWw } from "@webwriter/lit"; import "@shoelace-style/shoelace/dist/themes/light.css"; import { SlOption, SlSelect, SlButton, SlRange, SlIconButton, SlCheckbox, SlInput, SlColorPicker, SlDivider, SlButtonGroup, SlIcon, } from "@shoelace-style/shoelace"; import alignLeft from "@tabler/icons/outline/align-left.svg"; import alignRight from "@tabler/icons/outline/align-right.svg"; import alignCenter from "@tabler/icons/outline/align-center.svg"; @customElement("webwriter-gamebook-button") export class WebWriterGamebookButton extends LitElementWw { @property({ type: Number, reflect: true }) accessor dataTargetId: number; @property({ type: String, attribute: true, reflect: true }) accessor identifier: string; @property({ attribute: true }) accessor getNodeEditor = () => {}; //visual properties @property({ type: String, reflect: true }) accessor name: string = "Button"; @property({ type: String, reflect: true }) accessor size: string = "small"; @property({ type: Boolean, reflect: true }) accessor pill: boolean = false; @property({ type: Boolean, reflect: true }) accessor outline: boolean = false; @property({ type: Number, reflect: true }) accessor width: number = 50; @property({ type: String, reflect: true }) accessor alignment: string = "center"; @property({ type: String, reflect: true }) accessor variant: string = "default"; @property({ type: Number, attribute: true, reflect: true }) accessor tabIndex = -1; @query("sl-button") accessor button; static get scopedElements() { return { "sl-button": SlButton, "sl-select": SlSelect, "sl-option": SlOption, "sl-range": SlRange, "sl-icon-button": SlIconButton, "sl-checkbox": SlCheckbox, "sl-input": SlInput, "sl-color-picker": SlColorPicker, "sl-divider": SlDivider, "sl-button-group": SlButtonGroup, "sl-icon": SlIcon, }; } static get styles() { return css` :host(.highlighted) { border: 1px dashed #38bdf8; -webkit-box-shadow: 0 4px 30px 4px #c0c0c0; box-shadow: 0 4px 30px 4px #c0c0c0; } :host(:not([contenteditable="true"]):not([contenteditable=""])) .author-only { display: none; } :host([contenteditable="true"]) .author-only, :host([contenteditable=""]) .author-only { display: flex; flex-direction: column; box-sizing: border-box; padding-left: 10px; padding-bottom: 10px; gap: 12px; } .author-only .item { display: flex; flex-direction: column; gap: 7px; padding-bottom: 10px; } .author-only p { margin: 0px; font-weight: 500; font-size: 15px; box-sizing: border-box; /* border-bottom: 1.5px solid #52525b; */ color: #52525b; } .container { display: flex; width: 100%; } .controls p { padding: 0px; margin: 0px; } .active { background-color: #e0e0e0; /* example color for active state */ } sl-button.active::part(base) { background-color: #efefef; /* example color for active state */ } `; } firstUpdated() { (this.shadowRoot.querySelector("#sizeSelect") as SlSelect).value = this.size; (this.shadowRoot.querySelector("#pillCheckbox") as SlCheckbox).checked = this.pill; (this.shadowRoot.querySelector("#outlineCheckbox") as SlCheckbox).checked = this.outline; (this.shadowRoot.querySelector("#widthRange") as SlRange).value = this.width; (this.shadowRoot.querySelector("#variantSelect") as SlSelect).value = this.variant; this.addEventListener("mouseover", () => { const parsed = this.parseConnectionIdentifier(this.identifier); const event = new CustomEvent("hoverButton", { detail: { outputNodeId: parsed.outputNodeId, inputNodeId: parsed.inputNodeId, outputClass: parsed.outputClass, inputClass: "input_1", highlightButton: false, }, bubbles: true, // Allows the event to bubble up through the DOM composed: true, // Allows the event to pass through shadow DOM boundaries }); this.dispatchEvent(event); }); this.addEventListener("mouseleave", () => { const parsed = this.parseConnectionIdentifier(this.identifier); const event = new CustomEvent("leaveButton", { detail: { outputNodeId: parsed.outputNodeId, inputNodeId: parsed.inputNodeId, outputClass: parsed.outputClass, inputClass: "input_1", highlightButton: false, }, bubbles: true, // Allows the event to bubble up through the DOM composed: true, // Allows the event to pass through shadow DOM boundaries }); this.dispatchEvent(event); }); } handleSizeChange(e) { this.size = e.target.value; } handlePillChange(e) { this.pill = e.target.checked; } handleOutlineChange(e) { this.outline = e.target.checked; } handleWidthChange(e) { this.width = e.target.value; } handleVariantChange(e) { this.variant = e.target.value; } handleAlignmentChange(alignment) { this.alignment = alignment; } render() { return html`

${this.name}

Title

(this.name = e.target.value)} >

Size

Small Medium Large

Variant

Default Text Primary Success Neutral Warning Danger

Pill

Outline

Width

${this.width}%

Alignment

this.handleAlignmentChange("flex-start")} > this.handleAlignmentChange("center")} > this.handleAlignmentChange("flex-end")} >
`; } /* */ private parseConnectionIdentifier(identifier) { const parts = identifier.split("-"); const parsed = { outputNodeId: parseInt(parts[0]), outputClass: parts[1], inputNodeId: parseInt(parts[2]), inputClass: parts[3], }; return parsed; } }