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 22 private group: LitRadioGroup | undefined | null 23 private parent: LitRadioGroup | undefined | null 24 private radio: HTMLInputElement | undefined | null 25 26 static get observedAttributes() { 27 return ['checked', 'value'] 28 } 29 30 get checked() { 31 return this.getAttribute('checked') !== null; 32 } 33 34 set checked(value: boolean) { 35 if (value === null || !value) { 36 this.removeAttribute('checked'); 37 } else { 38 this.setAttribute('checked', ''); 39 } 40 } 41 42 get name() { 43 return this.getAttribute('name'); 44 } 45 46 get value() { 47 let slot = this.shadowRoot?.getElementById("slot") 48 return slot!.textContent || this.textContent || ""; 49 } 50 51 set value(value: string) { 52 this.setAttribute('value', value); 53 } 54 55 set dis(dis: string) { 56 this.setAttribute('dis', dis) 57 } 58 59 initHtml(): string { 60 return ` 61 <style> 62 :host([dis=round]):host{ 63 font-family: Helvetica,serif; 64 font-size: 14px; 65 color: var(--dark-color1,#212121); 66 text-align: left; 67 line-height: 16px; 68 font-weight: 400; 69 } 70 :host([dis=round]) lit-icon{ 71 display: none; 72 } 73 :host([dis=round]) #radio{ 74 position:absolute; 75 clip:rect(0,0,0,0); 76 } 77 :host([dis=round]) :host(:focus-within) .selected label:hover .selected{ 78 z-index:1; 79 border-color:#a671ef; 80 } 81 :host([dis=round]) label{ 82 box-sizing:border-box; 83 cursor:pointer; 84 display:flex; 85 align-items:center; 86 } 87 :host([dis=round]) .selected{ 88 position:relative; 89 display: flex; 90 box-sizing: border-box; 91 width: 16px; 92 height: 16px; 93 border-radius:50%; 94 border: 2px solid var(--dark-color1,#4D4D4D); 95 margin-right:1em; 96 } 97 .selected{ 98 position:relative; 99 box-sizing: border-box; 100 margin-right:1em; 101 } 102 :host([dis=round]) .selected::before{ 103 content:''; 104 width:6px; 105 height:6px; 106 margin:auto; 107 border-radius:50%; 108 background:#a671ef; 109 transform: scale(0); 110 } 111 :host([dis=round]) #radio:focus-visible+label .selected::after{ 112 transform:scale(2.5); 113 } 114 :host([dis=round]) #radio:checked+label .selected::before{ 115 transform: scale(1); 116 } 117 :host([dis=round]) #radio:checked+label .selected{ 118 border-color:#a671ef; 119 } 120 :host([dis=check]):host{ 121 opacity: 0.9; 122 font-family: Helvetica,serif; 123 font-size: 14px; 124 text-align: left; 125 font-weight: 400; 126 } 127 :host([dis=round]) lit-icon{ 128 visibility: visible; 129 } 130 :host([dis=check]) #radio{ 131 position:absolute; 132 clip:rect(0,0,0,0); 133 } 134 :host([dis=check]) label{ 135 box-sizing:border-box; 136 cursor:pointer; 137 display:flex; 138 align-items:center; 139 } 140 :host([dis=check]) .selected{ 141 position:relative; 142 display:flex; 143 justify-content: center; 144 align-items: center; 145 margin-right:5px; 146 width: 16px; 147 height:16px; 148 } 149 :host([dis=check]) .selected::before{ 150 position:absolute; 151 content:''; 152 width:74%; 153 height:0.15em; 154 background:#fff; 155 transform:scale(0); 156 border-radius: 0.15em; 157 } 158 :host([dis=check]) .selected::after{ 159 content:''; 160 position:absolute; 161 width:100%; 162 height:100%; 163 border-radius:50%; 164 background:#1A83FF; 165 opacity:0.2; 166 transform:scale(0); 167 z-index:-1; 168 } 169 :host([dis=check]) #radio:checked:not(:indeterminate)+label .selected .icon{ 170 transform: scale(1.5); 171 } 172 :host([dis=check]) #radio:indeterminate+label .selected::before{ 173 transform:scale(1); 174 } 175 :host([dis=check]) .icon{ 176 width: 90%; 177 height: 55%; 178 margin-left: 5px; 179 transform: scale(0); 180 } 181 :host([checked][dis=check]) { 182 background-color: #1A83FF; 183 color:#ffffff 184 } 185 </style> 186 <input type="checkbox" id="radio" > 187 <label id="label" for="radio"> 188 <span class="selected"> 189 <lit-icon name="checkmark" class="icon" size="8"> 190 </lit-icon> 191 </span> 192 <slot id='slot'></slot> 193 </label> 194 `; 195 } 196 197 initElements(): void { 198 this.radio = this.shadowRoot?.getElementById('radio') as HTMLInputElement; 199 } 200 201 connectedCallback() { 202 this.group = this.closest('lit-radio-group') as LitRadioGroup; 203 this.parent = this.group || this.getRootNode(); 204 this.radio = this.shadowRoot?.getElementById('radio') as HTMLInputElement; 205 this.checked = this.checked; 206 this.radio.addEventListener('change', () => { 207 const selector = this.group ? `lit-radio[checked]` : `lit-radio[name="${this.name}"][checked]`; 208 const siblingNode = this.parent?.querySelector(selector) as LitRadioBox; 209 if (siblingNode) { 210 siblingNode.checked = false; 211 } 212 this.checked = true; 213 }) 214 } 215 216 attributeChangedCallback(name: string, oldValue: string, newValue: string) { 217 if (name == 'checked' && this.radio) { 218 this.radio.checked = newValue !== null; 219 } 220 if (name == 'value') { 221 let slot = this.shadowRoot?.getElementById("slot") 222 slot!.textContent = newValue 223 } 224 } 225} 226