UNPKG

sf-checklist

Version:
378 lines (361 loc) 13.6 kB
/** * @license * Copyright 2022 Superflow.dev * SPDX-License-Identifier: MIT */ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { LitElement, html, css } from 'lit'; import { customElement, property } from 'lit/decorators.js'; /* Modes: multiselect, select Flows: view,edit */ /** * SfChecklist element. * @fires renderComplete - When the list is populated * @fires valueChanged - When the value is changed * @property apiId - backend api id * @property label - input label * @property name - name of the input * @property mode - mode of operation * @property selectedId - id to preselect * @property selectedValue - callback function */ let SfChecklist = class SfChecklist extends LitElement { constructor() { super(...arguments); // mode = "" this.mode = "admin"; this.readonly = false; // readonly = true this.listname = ""; this.listelements = []; // listelements: { name: string }[] = [ // { // "name": "Contract term 1" // }, // { // "name": "contract term 2" // }, // { // "name": "contract term 3" // } // ] // listelements: { name: string }[] = [{"name": "Terms1"},{"name": "Terms2"}] // listelements: { name: string }[] = [ // { // "name": "item 1" // }, // { // "name": "item 2" // } // ] this.listselection = {}; // listselection: { [key: string]: boolean } = { // "Contract term 1": true, // "contract term 2": true, // "contract term 3": true // } // listselection: any = { // "First term": true, // "Second term": true // } // listselection: any = { // "Check 1": true, // "Check 2": false, // "Check 3": true // } this.selectedValues = () => { console.log('checklist selectedvalues', JSON.stringify(this.listselection)); let retObj = {}; for (let key of this.listelements) { retObj[key] = this.listselection[key] ?? false; } return this.listselection; }; this.dispatchValueChanged = () => { console.log("dispatchValueChanged"); let customEvent = new CustomEvent('valueChanged', { detail: { source: 'InnerElement', id: this.id }, bubbles: true, composed: true }); this.dispatchEvent(customEvent); }; this.initListeners = () => { let addButton = this.shadowRoot?.getElementById("add-button"); let addInput = this.shadowRoot?.getElementById("add-input"); addButton?.addEventListener("click", () => { let newItem = addInput?.value; if (newItem) { // this.listelements.push({ name: newItem }); this.listselection[newItem] = false; addInput.value = ""; this.dispatchValueChanged(); this.loadMode(); } }); let deleteButtons = this.shadowRoot?.querySelectorAll('.button-delete'); for (let deleteButton of deleteButtons) { deleteButton.addEventListener('click', () => { let id = deleteButton.id; let index = parseInt(id.split('-')[2]); let listelement = this.listelements[index]; this.listelements.splice(index, 1); delete this.listselection[listelement]; this.dispatchValueChanged(); this.loadMode(); }); } let upButtons = this.shadowRoot?.querySelectorAll('.button-up'); for (let upButton of upButtons) { upButton.addEventListener('click', () => { let id = upButton.id; let index = parseInt(id.split('-')[2]); this.listelements = this.reorderArray(this.listelements, index, index - 1); let newMap = this.reorderMap(new Map(Object.entries(this.listselection)), this.listelements); this.listselection = Object.fromEntries(newMap); this.dispatchValueChanged(); this.loadMode(); }); } let downButtons = this.shadowRoot?.querySelectorAll('.button-down'); for (let downButton of downButtons) { downButton.addEventListener('click', () => { let id = downButton.id; let index = parseInt(id.split('-')[2]); this.listelements = this.reorderArray(this.listelements, index, index + 1); let newMap = this.reorderMap(new Map(Object.entries(this.listselection)), this.listelements); this.listselection = Object.fromEntries(newMap); this.dispatchValueChanged(); this.loadMode(); }); } }; this.loadMode = async () => { console.log("loadMode", this.mode, this.listelements, this.listselection); this.listelements = Object.keys(this.listselection); if (this.mode == "admin") { let checklistInputContainer = this.shadowRoot?.getElementById('checklist-input-container'); checklistInputContainer.style.display = this.readonly ? 'none' : 'flex'; let checklistList = this.shadowRoot?.getElementById("checklist-list"); let innerHTML = ''; if (Array.isArray(this.listelements)) { this.listelements.map((item, index) => { innerHTML += ` <div part="checklist-item" class="d-flex align-center"> <label part="checklist-checkbox-label">${(item ?? "")}</label>${!this.readonly && index > 0 ? `<button id="button-up-${index}" part="button-icon" class="mrl-5 material-symbols-outlined button-up">arrow_upward</button>` : ''}${!this.readonly && index < (this.listelements.length - 1) ? `<button id="button-down-${index}" part="button-icon" class="mrl-5 material-symbols-outlined button-down">arrow_downward</button>` : ''}${!this.readonly ? `<button id="button-delete-${index}" part="button-icon" class="mrl-5 material-icons button-delete">delete</button>` : ''} </div> `; }); } checklistList.innerHTML = innerHTML; console.log("checklistList", checklistList.innerHTML); if (!this.readonly) { this.initListeners(); } } else { let checklistList = this.shadowRoot?.getElementById("checklist-list"); let innerHTML = ''; if (Array.isArray(this.listelements)) { this.listelements.map((item) => { console.log('sf-checklistt rendering checkbox', this.listselection[(item ?? "")]); innerHTML += ` <div part="checklist-item" class="d-flex"> <input part="checklist-checkbox" type="checkbox" id="checkbox-${(item ?? "").replace(/ /g, '-')}" name="${(item ?? "")}" value="${(item ?? "")}" ${(this.listselection[(item ?? "")] ?? false) ? "checked" : ""} ${this.readonly ? "disabled" : ""}/> <label part="checklist-checkbox-label" for="checkbox-${(item ?? "").replace(/ /g, '-')}">${(item ?? "")}</label> </div> `; }); } checklistList.innerHTML = innerHTML; for (const item of this.listelements) { const checkbox = this.shadowRoot?.getElementById(`checkbox-${(item ?? "").replace(/ /g, '-')}`); if (checkbox) { checkbox.addEventListener('change', () => { const name = item ?? ""; this.listselection = { ...this.listselection, [name]: checkbox.checked }; console.log('checklist selected', this.listselection, typeof (this.listselection)); this.dispatchValueChanged(); }); } if (this.listselection[(item ?? "")] == null) { this.listselection[(item ?? "")] = false; } } this.dispatchValueChanged(); } }; } reorderArray(arr, oldIndex, newIndex) { if (oldIndex === newIndex) { return arr; } const newArr = [...arr]; const [item] = newArr.splice(oldIndex, 1); newArr.splice(newIndex, 0, item); return newArr; } reorderMap(map, newOrder) { const reordered = new Map(); for (const key of newOrder) { if (map.has(key)) { reordered.set(key, map.get(key)); } } return reordered; } firstUpdated(_changedProperties) { this.loadMode(); } connectedCallback() { super.connectedCallback(); } render() { if (this.mode == "admin") { return html ` <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" /> <div part="checklist-container" class="d-flex flex-col"> ${this.listname != "" ? `<h2 part="checklist-title">${this.listname}</h2>` : ''} <div id="checklist-input-container" part="checklist-input-container" class="d-flex"> <input part="checklist-add-input" type="text" id="add-input" name="add-input" value="" placeholder="Add new item" /> <button id="add-button" part="checklist-add-button" class="ml-10">Add</button> </div> <div id="checklist-list" part="checklist-list" class="d-flex flex-col flex-wrap justify-center w-100-m-0"> </div> </div> `; } else { return html ` <div part="checklist-container" class="d-flex"> ${this.listname != "" ? `<h2 part="checklist-title">${this.listname}</h2>` : ''} <div id="checklist-list" part="checklist-list" class="d-flex flex-col flex-wrap justify-center w-100-m-0"> </div> </div> `; } } }; SfChecklist.styles = css ` :root { --color: #fcc419; --shadow: #f08c00; --glare: hsl(0 0% 100% / 0.75); --font-size: clamp(.75rem, 2vw, 1rem); --transition: 0.2s; } * { box-sizing: border-box; } .d-flex { display: flex; } .flex-col { flex-direction: column; } .flex-wrap { flex-wrap: wrap; } .justify-center { justify-content: center; } .justify-between { justify-content: space-between; } .justify-end { justify-content: flex-end; } .w-100-m-0 { width: 100%; } .mb-20 { margin-bottom: 20px; } .mt-20 { margin-top: 20px; } .mr-10 { margin-right: 10px; } .m-0 { margin: 0px; } .m-20 { margin: 20px; } .md-20-ml-10 { margin-top: 20px; margin-bottom: 20px; margin-left: 10px; margin-right: 10px; } .mrl-5 { margin-left: 5px; margin-right: 5px; } .mrl-10 { margin-left: 10px; margin-right: 10px; } .mt-10{ margin-top: 10px } .ml-10{ margin-left: 10px } .mr-20{ margin-right: 20px } .flex-grow { flex-grow: 1; } .align-start { align-items: flex-start; } .align-end { align-items: flex-end; } .align-center { align-items: center; } .align-stretch { align-items: stretch; } body { display: grid; place-items: center; min-height: 100vh; font-family: 'Google Sans', sans-serif, system-ui; } `; __decorate([ property({ type: String }) ], SfChecklist.prototype, "mode", void 0); __decorate([ property({ type: Boolean }) ], SfChecklist.prototype, "readonly", void 0); __decorate([ property() ], SfChecklist.prototype, "listname", void 0); __decorate([ property({ type: Array }) ], SfChecklist.prototype, "listelements", void 0); __decorate([ property({ type: Object }) ], SfChecklist.prototype, "listselection", void 0); SfChecklist = __decorate([ customElement('sf-checklist') ], SfChecklist); export { SfChecklist }; //# sourceMappingURL=sf-checklist.js.map