1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import {BaseElement, element} from "../BaseElement.js"; 17import {LitRadioGroup} from "./LitRadioGroup.js"; 18 19@element('lit-radio') 20export class LitRadioBox extends BaseElement { 21 private group: LitRadioGroup | undefined | null 22 private parent: LitRadioGroup | undefined | null 23 private radio: HTMLInputElement | undefined | null 24 25 static get observedAttributes() { 26 return ['checked', 'value'] 27 } 28 29 get checked() { 30 return this.getAttribute('checked') !== null; 31 } 32 33 set checked(value: boolean) { 34 if (value === null || !value) { 35 this.removeAttribute('checked'); 36 } else { 37 this.setAttribute('checked', ''); 38 } 39 } 40 41 get name() { 42 return this.getAttribute('name'); 43 } 44 45 get value() { 46 let slot = this.shadowRoot?.getElementById("slot") 47 return slot!.textContent || this.textContent || ""; 48 } 49 50 set value(value: string) { 51 this.setAttribute('value', value); 52 } 53 54 set dis(dis: string) { 55 this.setAttribute('dis', dis) 56 } 57 58 initHtml(): string { 59 return ` 60 <style> 61 :host([dis=round]):host{ 62 font-family: Helvetica,serif; 63 font-size: 14px; 64 color: var(--dark-color1,#212121); 65 text-align: left; 66 line-height: 16px; 67 font-weight: 400; 68 } 69 :host([dis=round]) lit-icon{ 70 display: none; 71 } 72 :host([dis=round]) #radio{ 73 position:absolute; 74 clip:rect(0,0,0,0); 75 } 76 :host([dis=round]) :host(:focus-within) .selected label:hover .selected{ 77 z-index:1; 78 border-color:#a671ef; 79 } 80 :host([dis=round]) label{ 81 box-sizing:border-box; 82 cursor:pointer; 83 display:flex; 84 align-items:center; 85 } 86 :host([dis=round]) .selected{ 87 position:relative; 88 display: flex; 89 box-sizing: border-box; 90 width: 16px; 91 height: 16px; 92 border-radius:50%; 93 border: 2px solid var(--dark-color1,#4D4D4D); 94 margin-right:1em; 95 } 96 .selected{ 97 position:relative; 98 box-sizing: border-box; 99 margin-right:1em; 100 } 101 :host([dis=round]) .selected::before{ 102 content:''; 103 width:6px; 104 height:6px; 105 margin:auto; 106 border-radius:50%; 107 background:#a671ef; 108 transform: scale(0); 109 } 110 :host([dis=round]) #radio:focus-visible+label .selected::after{ 111 transform:scale(2.5); 112 } 113 :host([dis=round]) #radio:checked+label .selected::before{ 114 transform: scale(1); 115 } 116 :host([dis=round]) #radio:checked+label .selected{ 117 border-color:#a671ef; 118 } 119 :host([dis=check]):host{ 120 opacity: 0.9; 121 font-family: Helvetica,serif; 122 font-size: 14px; 123 text-align: left; 124 font-weight: 400; 125 } 126 :host([dis=round]) lit-icon{ 127 visibility: visible; 128 } 129 :host([dis=check]) #radio{ 130 position:absolute; 131 clip:rect(0,0,0,0); 132 } 133 :host([dis=check]) label{ 134 box-sizing:border-box; 135 cursor:pointer; 136 display:flex; 137 align-items:center; 138 } 139 :host([dis=check]) .selected{ 140 position:relative; 141 display:flex; 142 justify-content: center; 143 align-items: center; 144 margin-right:5px; 145 width: 16px; 146 height:16px; 147 } 148 :host([dis=check]) .selected::before{ 149 position:absolute; 150 content:''; 151 width:74%; 152 height:0.15em; 153 background:#fff; 154 transform:scale(0); 155 border-radius: 0.15em; 156 } 157 :host([dis=check]) .selected::after{ 158 content:''; 159 position:absolute; 160 width:100%; 161 height:100%; 162 border-radius:50%; 163 background:#1A83FF; 164 opacity:0.2; 165 transform:scale(0); 166 z-index:-1; 167 } 168 :host([dis=check]) #radio:checked:not(:indeterminate)+label .selected .icon{ 169 transform: scale(1.5); 170 } 171 :host([dis=check]) #radio:indeterminate+label .selected::before{ 172 transform:scale(1); 173 } 174 :host([dis=check]) .icon{ 175 width: 90%; 176 height: 55%; 177 margin-left: 5px; 178 transform: scale(0); 179 } 180 :host([checked][dis=check]) { 181 background-color: #1A83FF; 182 color:#ffffff 183 } 184 </style> 185 <input type="checkbox" id="radio" > 186 <label id="label" for="radio"> 187 <span class="selected"><lit-icon name="checkmark" class="icon" size="8"></lit-icon></span> 188 <slot id='slot'></slot> 189 </label> 190 `; 191 } 192 193 initElements(): void { 194 this.radio = this.shadowRoot?.getElementById('radio') as HTMLInputElement; 195 } 196 197 connectedCallback() { 198 this.group = this.closest('lit-radio-group') as LitRadioGroup; 199 this.parent = this.group || this.getRootNode(); 200 this.radio = this.shadowRoot?.getElementById('radio') as HTMLInputElement; 201 this.checked = this.checked; 202 this.radio.addEventListener('change', () => { 203 const selector = this.group ? `lit-radio[checked]` : `lit-radio[name="${this.name}"][checked]`; 204 const siblingNode = this.parent?.querySelector(selector) as LitRadioBox; 205 if (siblingNode) { 206 siblingNode.checked = false; 207 } 208 this.checked = true; 209 }) 210 } 211 212 attributeChangedCallback(name: string, oldValue: string, newValue: string) { 213 if (name == 'checked' && this.radio) { 214 this.radio.checked = newValue !== null; 215 } 216 if (name == 'value') { 217 let slot = this.shadowRoot?.getElementById("slot") 218 slot!.textContent = newValue 219 } 220 } 221} 222