Merge pull request #183 in YR/star-web-components from feature-value-selector to master
* commit '192ea982eec7cedc05a17b10274f997448312585': (feature)添加star-select及star-select-dialog,添加star-li type='selector',更新star-icons.ttf
This commit is contained in:
commit
0467a4955f
|
@ -456,6 +456,7 @@ const baseComponentStyle = css`
|
|||
--li-label: var(--font-main-black);
|
||||
--li-description: var(--font-sec-auxiliary-black);
|
||||
--li-square: #B3B3B3;
|
||||
--li-value-warn: var(--theme-red);
|
||||
--li-value-primary: var(--theme-blue);
|
||||
--li-value-default: var(--font-sec-auxiliary-black);
|
||||
--li-link: var(--linear-icon32-black);
|
||||
|
@ -468,6 +469,9 @@ const baseComponentStyle = css`
|
|||
--card-label: var(--font-main-black);
|
||||
--card-link: var(--linear-icon32-black);
|
||||
|
||||
/* Selector */
|
||||
--selector-icon-color: var(--linear-icon32-black);
|
||||
|
||||
/* Radio */
|
||||
--bor-radio-off: var(--auto-3px) solid rgba(38, 38, 38, 0.25);
|
||||
--bor-radio-off: var(--auto-3px) solid var(--opacity-white-25);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
| -------------- | ------- | -------- | -------------------------- |
|
||||
| vertical | Boolean | false | 用于指示是否显示垂直按钮组 |
|
||||
| split | Boolean | false | 用于指示是否显示分隔符 |
|
||||
| inheritRadius | Boolean | false | 用于指示是否继承倒角 |
|
||||
|
||||
<center><b>star-button-group组件支持的插槽</b></center>
|
||||
|
||||
|
@ -38,6 +39,11 @@ button-group 将 100% 填充父容器所给的空间,再均匀平铺\<slot\>
|
|||
<star-button type="text" variant="default" label="取消"></star-button>
|
||||
<star-button type="text" variant="primary" label="确定"></star-button>
|
||||
</star-button-group>
|
||||
|
||||
<star-button-group vertical split inheritRadius>
|
||||
<star-button type="text" variant="default" label="取消"></star-button>
|
||||
<star-button type="text" variant="primary" label="确定"></star-button>
|
||||
</star-button-group>
|
||||
```
|
||||
|
||||
## 注意
|
||||
|
|
|
@ -4,6 +4,7 @@ export default css`
|
|||
:host {
|
||||
--background-image-url: '';
|
||||
flex: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
div {
|
||||
|
|
|
@ -42,6 +42,9 @@ export class StarCard extends StarBaseElement {
|
|||
*/
|
||||
@property({type: Boolean, reflect: true}) checked!: boolean
|
||||
|
||||
/* 该value可供在扩展的 radio-group 中使用 */
|
||||
@property({type: String, reflect: true}) value!: string
|
||||
|
||||
@property({type: String}) type = 'base'
|
||||
// @property({type: String}) size = "medium"
|
||||
@property({type: String}) heading = ''
|
||||
|
|
|
@ -14,17 +14,48 @@
|
|||
基类采用的三段式结构:
|
||||
|
||||
```
|
||||
-------------------
|
||||
| 图标/标题 |
|
||||
-------------------
|
||||
| 内容 |
|
||||
| 纯文本/富文本/表单 |
|
||||
-------------------
|
||||
| 按钮/按钮组 |
|
||||
-------------------
|
||||
┌─────────────────────────────────────────────────┐
|
||||
| Header |
|
||||
├─────────────────────────────────────────────────|
|
||||
| ┌─────────────────────────────────────────────┐ |
|
||||
| │ Icon(star-icons/svg-icon/png...) │ |
|
||||
| └─────────────────────────────────────────────┘ |
|
||||
| ┌─────────────────────────────────────────────┐ |
|
||||
| │ Title(alert/confirm/prompt/select/Custom... │ |
|
||||
| └─────────────────────────────────────────────┘ |
|
||||
└─────────────────────────────────────────────────┘
|
||||
┌─────────────────────────────────────────────────┐
|
||||
| Content |
|
||||
├─────────────────────────────────────────────────|
|
||||
│ ┌──────┐ ┌───────┐ │
|
||||
│ │ Text │ │ Image │ │
|
||||
│ └──────┘ └───────┘ │
|
||||
│ ┌──────────────────────────────────────┐ │
|
||||
│ │ Form │ │
|
||||
│ │ ┌─────────────────┐ ┌──────────────┐ │ │
|
||||
│ │ │ Input(Password) │ │ ActionButton │ │ │
|
||||
│ │ └─────────────────┘ └──────────────┘ │ │
|
||||
│ └──────────────────────────────────────┘ │
|
||||
│ ┌────────────────────────────────┐ │
|
||||
│ │ Select (Multiple)(Group)(Size) │ │
|
||||
│ │ ┌────────────┐ │ │
|
||||
│ │ │ RadioGroup │ │ │
|
||||
│ │ └────────────┘ │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
┌─────────────────────────────────────────────────┐
|
||||
| Footer |
|
||||
├─────────────────────────────────────────────────|
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ StarButtonGroup │ │
|
||||
│ │ ┌────────────┐ ┌────────────┐ │ │
|
||||
│ │ │ StarButton │ │ StarButton │ ... │ │
|
||||
│ │ └────────────┘ └────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 系统弹窗(alert/confirm/prompt)
|
||||
## 系统模态弹窗(alert/confirm/prompt)
|
||||
|
||||
```
|
||||
alert
|
||||
|
@ -53,6 +84,112 @@ prompt
|
|||
-------------------
|
||||
```
|
||||
|
||||
## 系统用户代理弹窗(select)
|
||||
|
||||
### 值选择器
|
||||
|
||||
对应使用的原生标签:
|
||||
|
||||
```html
|
||||
<!-- 基础选择器 -->
|
||||
<select id="singleSel">
|
||||
<option value="Mozilla">Mozilla</option>
|
||||
<option value="B2G">B2G</option>
|
||||
<option value="Gaia">Gaia</option>
|
||||
<option value="Gecko">Gecko</option>
|
||||
<option value="Basecamp">Basecamp</option>
|
||||
</select>
|
||||
|
||||
<!-- 带size属性 -->
|
||||
<select size="3" id="sizeSel">
|
||||
<option value="Mozilla">Mozilla</option>
|
||||
<option value="B2G">B2G</option>
|
||||
<option value="Gaia">Gaia</option>
|
||||
<option value="Gecko">Gecko</option>
|
||||
<option value="Basecamp">Basecamp</option>
|
||||
</select>
|
||||
|
||||
<!-- 多选选择器, 待mulitiple属性 -->
|
||||
<select multiple="multiple" id="multiSel">
|
||||
<option value="Mozilla">Mozilla</option>
|
||||
<option value="B2G">B2G</option>
|
||||
<option value="Gaia">Gaia</option>
|
||||
<option value="Gecko">Gecko</option>
|
||||
<option value="Basecamp">Basecamp</option>
|
||||
</select>
|
||||
|
||||
<!-- 分类选择器, 子标签是<optgroup> -->
|
||||
<select name="groups" size="6">
|
||||
<optgroup label="B2G">
|
||||
<option value="Gonk">Gonk</option>
|
||||
<option value="Gecko">Gecko</option>
|
||||
<option value="Gaia">Gaia</option>
|
||||
</optgroup>
|
||||
<optgroup label="Devices">
|
||||
<option value="otoro">Otoro</option>
|
||||
<option value="hamachi">Hamachi</option>
|
||||
<option value="flame">Flame</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
```
|
||||
|
||||
### 时间日期选择器
|
||||
|
||||
```html
|
||||
<!-- 单时间 -->
|
||||
<input type="time" placeholder="Time" />
|
||||
<!-- 单日期 -->
|
||||
<input type="date" placeholder="Date" />
|
||||
<!-- 预设值 -->
|
||||
<input type="date" placeholder="Time" value="2016-05-20" />
|
||||
<input type="time" placeholder="Time" value="10:14" />
|
||||
```
|
||||
|
||||
### UI 设计内容
|
||||
|
||||
触发形态:
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
┌───────────┐
|
||||
| Header |
|
||||
├───────────|
|
||||
| ┌───────┐ |
|
||||
| │ Title │ |
|
||||
| └───────┘ |
|
||||
└───────────┘
|
||||
┌─────────────────────────────────────────────────┐
|
||||
| Content |
|
||||
├─────────────────────────────────────────────────|
|
||||
│ ┌─single select──────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────────┐ │ │
|
||||
│ │ │ RadioGroup │ │ │
|
||||
│ │ └────────────┘ │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
┌───────────────────────────────────┐
|
||||
| Footer |
|
||||
├───────────────────────────────────|
|
||||
│ ┌───────────────────────────────┐ │
|
||||
│ │ StarButtonGroup │ │
|
||||
│ ├─────────single select─────────| │
|
||||
│ │ ┌────────────┐ │ │
|
||||
│ │ │ StarButton │ │ │
|
||||
│ │ └────────────┘ │ │
|
||||
│ ├───────multiple select─────────| │
|
||||
│ │ ┌────────────┐ ┌────────────┐ │ │
|
||||
│ │ │ StarButton │ │ StarButton │ │ │
|
||||
│ │ └────────────┘ └────────────┘ │ │
|
||||
│ └───────────────────────────────┘ │
|
||||
└───────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 转换
|
||||
|
||||
## TBD: 使用用户代理支持的<dialog>
|
||||
|
||||
使用浏览器用户代理支持的<dialog>时,可以省去自行设定模态的步骤,并且其自身已经拥有了默认排版,省去设置样式的行为。
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export {StarAlertDialog} from './alert-dialog.js'
|
||||
export {StarConfirmDialog} from './confirm-dialog.js'
|
||||
export {StarPromptDialog} from './prompt-dialog.js'
|
||||
export {StarSelectDialog} from './select-dialog.js'
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import {css} from 'lit'
|
||||
|
||||
export default css`
|
||||
.star-select-title {
|
||||
color: var(--dialog-heading);
|
||||
font-size: var(--auto-28px);
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: var(--auto-36px);
|
||||
max-height: var(--auto-524px);
|
||||
}
|
||||
|
||||
main {
|
||||
--oc-li-padding-inline: var(--auto-60px);
|
||||
--oc-li-min-height: var(--auto-90px);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
star-radio-group {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
max-height: calc(var(--auto-90px) * 4);
|
||||
}
|
||||
|
||||
star-radio-group[multiple] star-li[checked] {
|
||||
--li-label: var(--theme-blue);
|
||||
}
|
||||
|
||||
star-card {
|
||||
padding: 10px 0;
|
||||
}
|
||||
`
|
|
@ -0,0 +1,291 @@
|
|||
import {
|
||||
customElement,
|
||||
html,
|
||||
nothing,
|
||||
query,
|
||||
state,
|
||||
CSSResultArray,
|
||||
TemplateResult,
|
||||
} from '@star-web-components/base/star-base-element.js'
|
||||
import StarBaseDialog from './base-dialog.js'
|
||||
import selectDialogStyles from './select-dialog.css.js'
|
||||
import '@star-web-components/button/button.js'
|
||||
import '@star-web-components/button-group/button-group.js'
|
||||
import '@star-web-components/radio'
|
||||
import {StarButton} from '@star-web-components/button'
|
||||
import {StarLi} from '@star-web-components/li'
|
||||
import {StarRadioGroup} from '@star-web-components/radio'
|
||||
|
||||
interface SelectDialogOptions {
|
||||
title?: string
|
||||
type: string | 'select'
|
||||
subtitle?: string
|
||||
image?: string
|
||||
cancel?: string
|
||||
confirm?: string
|
||||
oncancel?: () => void
|
||||
onconfirm?: (e: Event) => void
|
||||
onselect?: (e: Event) => void
|
||||
multiple?: boolean
|
||||
optionsSlot: StarLi[] | TemplateResult
|
||||
}
|
||||
|
||||
/**
|
||||
* 租借子节点
|
||||
*
|
||||
* 将一组元素租给一个目标元素,在该组元素的原位置使用注释占位符进行替代,
|
||||
* 并返回一个归还节点的方法.
|
||||
*
|
||||
* 原理: 剖析单个元素的租借过程
|
||||
* 1. 找到元素的父节点(parentElement 或 getRootNode())
|
||||
* 2. 在元素的父节点处将元素替换为注释占位符的节点拷贝
|
||||
* 3. 在目标位置插入租借来的元素
|
||||
* 4. 返回归还租借的子节点的方法
|
||||
*/
|
||||
export const reparentChildren = <T extends Element>(
|
||||
srcElements: T[],
|
||||
destination: Element,
|
||||
{
|
||||
position,
|
||||
prepareCallback,
|
||||
}: {
|
||||
position: InsertPosition
|
||||
prepareCallback?: (el: T) => ((el: T) => void) | void
|
||||
} = {
|
||||
position: 'beforeend',
|
||||
}
|
||||
): (() => T[]) => {
|
||||
let {length} = srcElements
|
||||
if (length === 0) return () => srcElements
|
||||
|
||||
let step = 1
|
||||
let index = 0
|
||||
|
||||
if (position === 'afterbegin' || position === 'afterend') {
|
||||
step = -1
|
||||
index = length - 1
|
||||
}
|
||||
|
||||
const placeholderItems = new Array<Comment>(length)
|
||||
const cleanupCallbacks = new Array<(el: T) => void>(length)
|
||||
const placeholderTemplate: Comment = document.createComment(
|
||||
'placeholder for reparented element'
|
||||
)
|
||||
|
||||
do {
|
||||
const srcElement = srcElements[index]
|
||||
if (prepareCallback) {
|
||||
cleanupCallbacks[index] = prepareCallback(srcElement) as (el: T) => void
|
||||
}
|
||||
placeholderItems[index] = placeholderTemplate.cloneNode() as Comment
|
||||
|
||||
const parentElement = srcElement.parentElement || srcElement.getRootNode()
|
||||
if (parentElement && parentElement !== srcElement) {
|
||||
parentElement.replaceChild(placeholderItems[index], srcElement)
|
||||
}
|
||||
destination.insertAdjacentElement(position, srcElement)
|
||||
index += step
|
||||
} while (--length > 0)
|
||||
|
||||
return (): T[] =>
|
||||
restoreChildren<T>(placeholderItems, srcElements, cleanupCallbacks)
|
||||
}
|
||||
|
||||
/**
|
||||
* 归还子节点
|
||||
*
|
||||
* 是租借子节点的逆过程, 将注释占位符替换成子节点, 再删除注释占位符
|
||||
*/
|
||||
export const restoreChildren = <T extends Element>(
|
||||
placeholderItems: Comment[],
|
||||
srcElements: T[],
|
||||
cleanupCallbacks: ((el: T) => void)[] = []
|
||||
): T[] => {
|
||||
for (let index = 0; index < srcElements.length; ++index) {
|
||||
const srcElement = srcElements[index]
|
||||
const placeholderItem = placeholderItems[index]
|
||||
const parentElement =
|
||||
placeholderItem.parentElement || placeholderItem.getRootNode()
|
||||
cleanupCallbacks[index]?.(srcElement)
|
||||
if (parentElement && parentElement !== placeholderItem) {
|
||||
parentElement.replaceChild(srcElement, placeholderItem)
|
||||
}
|
||||
delete placeholderItems[index]
|
||||
}
|
||||
return srcElements
|
||||
}
|
||||
|
||||
@customElement('star-select-dialog')
|
||||
export class StarSelectDialog extends StarBaseDialog {
|
||||
constructor(obj: SelectDialogOptions) {
|
||||
super()
|
||||
this.title = obj.title || this.title
|
||||
this.type = obj.type
|
||||
this.cancel = obj.cancel || '取消'
|
||||
this.confirm = obj.confirm || '确定'
|
||||
this.oncancel = obj.oncancel || (() => {})
|
||||
this.onconfirm = obj.onconfirm || (() => {})
|
||||
this.onselect = obj.onselect || (() => {})
|
||||
this.optionsSlot = obj.optionsSlot
|
||||
this.multiple = obj.multiple || false
|
||||
}
|
||||
|
||||
public static override get styles(): CSSResultArray {
|
||||
return [super.styles, selectDialogStyles]
|
||||
}
|
||||
|
||||
@state() type!: string
|
||||
|
||||
@state() multiple = false
|
||||
|
||||
@state() title = '提示'
|
||||
|
||||
@query('star-radio-group') radioGroup!: StarRadioGroup
|
||||
|
||||
@query("star-button[variant='primary']") confirmButton!: StarButton
|
||||
|
||||
text!: string
|
||||
|
||||
optionsSlot!: StarLi[] | TemplateResult
|
||||
|
||||
/* 记录初始化的选择项,用于取消时重置 */
|
||||
initSelected!: string
|
||||
|
||||
reparentThenRestore!: Function
|
||||
|
||||
@state() optionsTemplateResult: TemplateResult | typeof nothing = nothing
|
||||
|
||||
protected override get headerContent(): TemplateResult {
|
||||
return html`
|
||||
<div class="star-base-main">
|
||||
<div class="star-select-title">${this.title}</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
/**
|
||||
* 针对用户代理的select, 填充基本款:
|
||||
* <star-raido-gorup>
|
||||
* <star-radio>
|
||||
* ...
|
||||
* </star-radio-group>
|
||||
*
|
||||
* 针对自定义的select, 从来源处租借符合radio特征的slot插槽中的选择项:
|
||||
* <star-raido-gorup>
|
||||
* <mock-radio...>
|
||||
* ...
|
||||
* </star-radio-group>
|
||||
*/
|
||||
protected override get mainContent(): TemplateResult {
|
||||
return html`
|
||||
<star-radio-group @change=${this.handleSelect} ?multiple=${this.multiple}>
|
||||
${Array.isArray(this.optionsSlot) ? nothing : this.optionsSlot}
|
||||
</star-radio-group>
|
||||
`
|
||||
}
|
||||
|
||||
/**
|
||||
* 针对不同的选择器类型:使用不同的底部按钮组
|
||||
*
|
||||
*
|
||||
*/
|
||||
protected override get bottomContent(): TemplateResult {
|
||||
switch (this.type) {
|
||||
case 'select': {
|
||||
if (this.multiple === false) {
|
||||
return html`
|
||||
<star-button-group inheritRadius>
|
||||
<star-button
|
||||
type="text"
|
||||
label=${this.cancel}
|
||||
variant="primary"
|
||||
@click=${this.handleCancel}
|
||||
></star-button>
|
||||
</star-button-group>
|
||||
`
|
||||
} else {
|
||||
return html`
|
||||
<star-button-group inheritRadius split>
|
||||
<star-button
|
||||
type="text"
|
||||
label=${this.cancel}
|
||||
@click=${this.handleCancel}
|
||||
></star-button>
|
||||
<star-button
|
||||
type="text"
|
||||
label=${this.confirm}
|
||||
variant="primary"
|
||||
@click=${this.handleConfirm}
|
||||
></star-button>
|
||||
</star-button-group>
|
||||
`
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new Error("Unhandled type in SelectDialog' bottom content")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 multiple 模式中退出时,重置 StarRadioGroup 中的选择项
|
||||
*/
|
||||
handleCancel(e: Event) {
|
||||
if (this.multiple === true) {
|
||||
this.radioGroup.setSelected(this.initSelected)
|
||||
}
|
||||
super.handleCancel(e)
|
||||
this.reparentThenRestore?.()
|
||||
}
|
||||
|
||||
override handleConfirm(e: Event) {
|
||||
super.handleConfirm(e)
|
||||
this.reparentThenRestore?.()
|
||||
}
|
||||
|
||||
handleSelect(e: Event) {
|
||||
this.onselect?.(e)
|
||||
if (this.multiple === false) {
|
||||
super.handleCancel(e)
|
||||
this.reparentThenRestore?.()
|
||||
} else {
|
||||
if (this.radioGroup.getSelected() === '') {
|
||||
this.confirmButton.setAttribute('disabled', '')
|
||||
} else {
|
||||
this.confirmButton.removeAttribute('disabled')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected firstUpdated(_: any) {
|
||||
super.firstUpdated(_)
|
||||
if (Array.isArray(this.optionsSlot)) {
|
||||
this.reparentThenRestore = reparentChildren(
|
||||
this.optionsSlot,
|
||||
this.radioGroup
|
||||
)
|
||||
} else {
|
||||
// 再将 star-radio-group 下的内容解析为数组,重置于 optionsSlot 上
|
||||
this.optionsSlot = [
|
||||
...this.querySelectorAll('star-radio-group *'),
|
||||
] as StarLi[]
|
||||
}
|
||||
|
||||
for (const radio of this.optionsSlot) {
|
||||
if (radio.checked === true) {
|
||||
this.updateComplete.then(() => {
|
||||
// 平滑滚动至默认选择项
|
||||
radio.scrollIntoView({behavior: 'smooth'})
|
||||
// 保存初始化的选项
|
||||
this.initSelected = this.radioGroup.getSelected()
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'star-select-dialog': StarSelectDialog
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_152_6195)">
|
||||
<path d="M7 25L25 7M7 7L25 25" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_152_6195">
|
||||
<rect width="32" height="32" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 361 B |
Binary file not shown.
|
@ -76,18 +76,6 @@
|
|||
</star-li>
|
||||
```
|
||||
|
||||
```
|
||||
## 电池
|
||||
-------- ----------------
|
||||
| Icon | | 主Label | 分隔线 灰色状态值VALUE
|
||||
-------- ----------------
|
||||
|
||||
########################################----SLOT
|
||||
----------------
|
||||
| 主Label | Slot-选择器Selector(值选择器, 时间选择器, 日期选择器)
|
||||
----------------
|
||||
```
|
||||
|
||||
## (inline)内联及模拟
|
||||
|
||||
### type="checkbox"
|
||||
|
@ -291,6 +279,55 @@
|
|||
</star-radio-group>
|
||||
```
|
||||
|
||||
### type="selector" 中与 select 标签的交互
|
||||
|
||||
结构:
|
||||
|
||||
```
|
||||
┌───────────────┬──────────────────────────────────────────────────┐
|
||||
│ │ ┌─────────┐ ┌───────┬────────┐ ┌───────────────┐ │
|
||||
│ <star-li> │ │ │ │ Label │ Square │ │ │ │
|
||||
│ │ │(App)Icon│ ├───────┴────────┤ │ Select │ │
|
||||
│type='selector'│ │ │ │ Description | │Single/Multiple│ │
|
||||
│ │ └─────────┘ └────────────────┘ └───────────────┘ │
|
||||
└───────────────┴──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
基本示例:
|
||||
|
||||
```html
|
||||
<star-li type="selector" label="自动熄屏" selected="30">
|
||||
<star-select slot="select" selected="15">
|
||||
<option label="15秒" value="15"></option>
|
||||
<option label="30秒" value="30"></option>
|
||||
<option label="60秒" value="60"></option>
|
||||
<option label="永不" value="never"></option>
|
||||
</star-select>
|
||||
</star-li>
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
1. selected 优先级: star-li > select, select 上的 selected 可被 star-li 覆写
|
||||
2. 点击 star-li 的选择器区域时,用户的实际点击事件将到达 select 标签(非 trusted 的 click 事件将无法打开用户代理的 select 窗)
|
||||
|
||||
实际显示的弹窗内的 dom 结构:
|
||||
|
||||
```html
|
||||
<star-select-dialog label="自动熄屏">
|
||||
<header...>
|
||||
<content>
|
||||
<star-radio-group select="inherit select">
|
||||
<option label="15秒" value="15"></option>
|
||||
<option label="30秒" value="30"></option>
|
||||
<option label="60秒" value="60"></option>
|
||||
<option label="永不" value="never"></option>
|
||||
</star-radio-group>
|
||||
</content>
|
||||
<footer...>
|
||||
</star-select-dialog>
|
||||
```
|
||||
|
||||
## 完全插槽态
|
||||
|
||||
### type='base' `star-card` 在 `star-li` 中
|
||||
|
|
|
@ -5,7 +5,7 @@ export default css`
|
|||
display: flex;
|
||||
padding-inline: var(--oc-li-padding-inline, var(--auto-48px));
|
||||
width: calc(100% - var(--oc-li-padding-inline, var(--auto-48px)) * 2);
|
||||
min-height: var(--auto-96px);
|
||||
min-height: var(--oc-li-min-height, var(--auto-96px));
|
||||
}
|
||||
li {
|
||||
width: 100%;
|
||||
|
@ -105,7 +105,7 @@ export default css`
|
|||
span#label {
|
||||
font-weight: bold;
|
||||
color: var(--li-label);
|
||||
font-weight: 400px;
|
||||
font-weight: 400;
|
||||
font-size: var(--auto-26px);
|
||||
line-height: var(--auto-34px);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ export default css`
|
|||
margin: auto var(--auto-16px) var(--auto-1px) var(--auto-16px);
|
||||
padding-inline: var(--auto-8px);
|
||||
line-height: var(--auto-23px);
|
||||
font-weight: 500px;
|
||||
font-weight: 500;
|
||||
font-size: var(--auto-20px);
|
||||
color: var(--li-square);
|
||||
}
|
||||
|
@ -129,9 +129,9 @@ export default css`
|
|||
}
|
||||
span#description {
|
||||
color: var(--li-description);
|
||||
font-weight: 400px;
|
||||
font-weight: 400;
|
||||
font-size: var(--auto-20px);
|
||||
line-height: var(--auto-18px);
|
||||
line-height: var(--auto-20px);
|
||||
margin-top: var(--auto-12px);
|
||||
}
|
||||
span#value {
|
||||
|
@ -148,6 +148,9 @@ export default css`
|
|||
:host([variant='primary']) span#value {
|
||||
color: var(--li-value-primary);
|
||||
}
|
||||
:host([variant='warn']) span#value {
|
||||
color: var(--li-value-warn);
|
||||
}
|
||||
|
||||
/* 边界折叠 */
|
||||
span#label,
|
||||
|
@ -180,7 +183,7 @@ export default css`
|
|||
box-sizing: border-box;
|
||||
vertical-align: top;
|
||||
text-align: right;
|
||||
font-weight: 400px;
|
||||
font-weight: 400;
|
||||
font-size: var(--auto-26px);
|
||||
line-height: var(--auto-26px);
|
||||
color: var(--li-input);
|
||||
|
@ -202,6 +205,7 @@ export default css`
|
|||
content: ' ';
|
||||
width: var(--auto-32px);
|
||||
height: var(--auto-32px);
|
||||
min-width: var(--auto-32px);
|
||||
margin: auto 0px auto auto;
|
||||
box-sizing: border-box;
|
||||
border: var(--auto-3px) solid rgba(38, 38, 38, 0.2);
|
||||
|
@ -335,7 +339,7 @@ export default css`
|
|||
--oc-text-padding-inline: 0px;
|
||||
--oc-text-min-width: min-width;
|
||||
margin: auto 0px auto auto;
|
||||
font-weight: 400px;
|
||||
font-weight: 400;
|
||||
font-size: var(--auto-26px);
|
||||
line-height: var(--auto-34px);
|
||||
color: var(--font-auxiliary-black);
|
||||
|
@ -343,6 +347,12 @@ export default css`
|
|||
::slotted(star-slider[slot='slider']) {
|
||||
width: 100%;
|
||||
}
|
||||
::slotted(star-select[slot='select']) {
|
||||
margin: auto 0px auto auto;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 条目按压和释放时的变化 */
|
||||
:host(.starpress:not([type='base'], [type='embed-switch'], [type='embed-checkbox'])) {
|
||||
|
|
|
@ -26,7 +26,7 @@ export enum LiType {
|
|||
CHECKBOX = 'checkbox',
|
||||
INPUT = 'input',
|
||||
RADIO = 'radio',
|
||||
/* todo */ SELECTOR = 'selector',
|
||||
SELECTOR = 'selector',
|
||||
SWITCH = 'switch',
|
||||
|
||||
/* 嵌入式 */
|
||||
|
@ -313,6 +313,10 @@ export class StarLi extends StarBaseElement {
|
|||
return html`
|
||||
<slot name="slider-button"></slot>
|
||||
`
|
||||
case LiType.SELECTOR:
|
||||
return html`
|
||||
<slot name="select"></slot>
|
||||
`
|
||||
case LiType.SWITCH:
|
||||
return html`
|
||||
<star-switch
|
||||
|
@ -404,9 +408,6 @@ export class StarLi extends StarBaseElement {
|
|||
/* deprecated */ case LiType.ONLY_READ:
|
||||
return this.getonlyread()
|
||||
|
||||
case LiType.SELECTOR:
|
||||
// TBD
|
||||
|
||||
case LiType.EMBED_CHECKBOX:
|
||||
case LiType.EMBED_INFO:
|
||||
case LiType.EMBED_SLIDER:
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
import {css, html, CSSResultArray, LitElement, PropertyValues} from 'lit'
|
||||
import {customElement, property} from 'lit/decorators.js'
|
||||
import {
|
||||
css,
|
||||
customElement,
|
||||
html,
|
||||
property,
|
||||
CSSResultArray,
|
||||
StarBaseElement,
|
||||
} from '@star-web-components/base/star-base-element.js'
|
||||
import {StarRadio, RadioVariant} from './radio.js'
|
||||
import {sharedStyles} from './radio-style.js'
|
||||
|
||||
@customElement('star-radio-group')
|
||||
export class StarRadioGroup extends LitElement {
|
||||
export class StarRadioGroup extends StarBaseElement {
|
||||
public static override get styles(): CSSResultArray {
|
||||
return [
|
||||
sharedStyles,
|
||||
|
@ -26,6 +32,8 @@ export class StarRadioGroup extends LitElement {
|
|||
// 默认为水平
|
||||
@property({type: Boolean, reflect: true}) vertical = false
|
||||
|
||||
@property({type: Boolean, reflect: true}) multiple = false
|
||||
|
||||
/**
|
||||
* radio 选中样式的控制, 支持: circle(默认), checkmark,
|
||||
* 可覆写包含的 child radio样式.
|
||||
|
@ -44,6 +52,50 @@ export class StarRadioGroup extends LitElement {
|
|||
})
|
||||
}
|
||||
|
||||
public get activeRadios(): StarRadio[] {
|
||||
return Array.prototype.filter.call(this.children, (child) => {
|
||||
if (child instanceof StarRadio) {
|
||||
return true
|
||||
} else if (child.type === 'radio' && child.checked === true) {
|
||||
/* 非 <star-radio>, 但是具有同样表现的标签扩展 */
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
public get label(): string {
|
||||
return [...this.activeRadios].reduce((sum, radio) => {
|
||||
if (sum === '') return radio.label
|
||||
else return (sum += ',' + radio.label)
|
||||
}, '')
|
||||
}
|
||||
|
||||
public setSelected(str: string): boolean {
|
||||
try {
|
||||
const selected = str.split(',')
|
||||
for (const radio of this.radios) {
|
||||
if (selected.includes(radio.value)) {
|
||||
radio.checked = true
|
||||
} else {
|
||||
radio.checked = false
|
||||
}
|
||||
}
|
||||
this.emit('change')
|
||||
return true
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public getSelected(): string {
|
||||
return [...this.activeRadios].reduce((sum, radio) => {
|
||||
if (sum === '') return radio.value
|
||||
else return (sum += ',' + radio.value)
|
||||
}, '')
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div id="star-radio-group" @click=${this}>
|
||||
|
@ -52,7 +104,7 @@ export class StarRadioGroup extends LitElement {
|
|||
`
|
||||
}
|
||||
|
||||
handleEvent(evt: Event) {
|
||||
_onSingleRadioClick(evt: Event) {
|
||||
const target = evt.target as StarRadio
|
||||
if (this.radios.indexOf(target) !== -1 && target.checked !== true) {
|
||||
target.checked = true
|
||||
|
@ -61,18 +113,26 @@ export class StarRadioGroup extends LitElement {
|
|||
radio.checked = false
|
||||
}
|
||||
}
|
||||
this.selected = target.value
|
||||
this.dispatchEvent(
|
||||
new Event('change', {
|
||||
bubbles: true,
|
||||
composed: false,
|
||||
})
|
||||
)
|
||||
this.emit('change')
|
||||
}
|
||||
}
|
||||
|
||||
protected override firstUpdated(changes: PropertyValues): void {
|
||||
super.firstUpdated(changes)
|
||||
_onMultipleRadioClick(evt: Event) {
|
||||
const target = evt.target as StarRadio
|
||||
if (this.radios.indexOf(target) !== -1) {
|
||||
target.checked = !target.checked
|
||||
this.emit('change')
|
||||
}
|
||||
}
|
||||
|
||||
handleEvent(evt: Event) {
|
||||
;(this.multiple
|
||||
? this._onMultipleRadioClick
|
||||
: this._onSingleRadioClick
|
||||
).call(this, evt)
|
||||
}
|
||||
|
||||
protected override firstUpdated(): void {
|
||||
for (const radio of this.radios) {
|
||||
if (radio.value === this.selected) {
|
||||
radio.checked = true
|
||||
|
|
|
@ -1,8 +1,155 @@
|
|||
# 选择
|
||||
|
||||
如: iPhone-通用-键盘-听写语言
|
||||
star-select 的作用: 将原生 \<select\> 标签包装为自定义的 UI 设计样式.
|
||||
|
||||
## 特点
|
||||
|
||||
- 支持多选
|
||||
- 强制多选类型`的情况下,选择只有一个时,将其置灰
|
||||
|
||||
## 数据结构
|
||||
|
||||
### detail.type="SELECT" && detail.choices.multiple: false
|
||||
|
||||
`isFocus``js
|
||||
{
|
||||
bubbles: false
|
||||
cancelBubble: false
|
||||
cancelable: false
|
||||
composed: false
|
||||
composedTarget: ...
|
||||
currentTarget: ...
|
||||
defaultPrevented: false
|
||||
defaultPreventedByChrome: false
|
||||
defaultPreventedByContent: false
|
||||
detail: {
|
||||
activeEditable: Object { native: XPCWrappedNative_NoHelper }
|
||||
choices: XPCWrappedNative_NoHelper {
|
||||
...
|
||||
multiple: false,
|
||||
choices: (5) [XPCWrappedNative_NoHelper, XPCWrappedNative_NoHelper, XPCWrappedNative_NoHelper, …],
|
||||
...
|
||||
}
|
||||
imeGroup: null
|
||||
inputMode: null
|
||||
inputType: null
|
||||
isFocus: true
|
||||
lang: null
|
||||
lastImeGroup: ""
|
||||
max: null
|
||||
maxLength: null
|
||||
min: null
|
||||
name: null
|
||||
selectionEnd: 0
|
||||
selectionStart: 0
|
||||
type: "SELECT"
|
||||
value: ""
|
||||
voiceInputSupported: false
|
||||
}
|
||||
eventPhase: 2
|
||||
explicitOriginalTarget: ...
|
||||
isReplyEventFromRemoteContent: false
|
||||
isSynthesized: false
|
||||
isTrusted: true
|
||||
isWaitingReplyFromRemoteContent: false
|
||||
multipleActionsPrevented: false
|
||||
originalTarget: ...
|
||||
returnValue: true
|
||||
srcElement: ...
|
||||
target: ...
|
||||
timeStamp: 80988671.942999
|
||||
type: "\_inputmethod-contextchange"
|
||||
}
|
||||
|
||||
````
|
||||
|
||||
### detail.type="SELECT" && detail.choices.multiple: true
|
||||
|
||||
```js
|
||||
choices: XPCWrappedNative_NoHelper {
|
||||
...
|
||||
multiple: true,
|
||||
choices: (5) [XPCWrappedNative_NoHelper, XPCWrappedNative_NoHelper, XPCWrappedNative_NoHelper, …],
|
||||
...
|
||||
}
|
||||
````
|
||||
|
||||
### detail.type="INPUT"
|
||||
|
||||
#### detail.inputType="time"
|
||||
|
||||
```js
|
||||
detail: {
|
||||
activeEditable: {…}
|
||||
choices: XPCWrappedNative_NoHelper
|
||||
imeGroup: null
|
||||
inputMode: null
|
||||
inputType: "time"
|
||||
isFocus: true
|
||||
lang: null
|
||||
lastImeGroup: ""
|
||||
max: null
|
||||
maxLength: null
|
||||
min: null
|
||||
name: null
|
||||
selectionEnd: 0
|
||||
selectionStart: 0
|
||||
type: "INPUT"
|
||||
value: ""
|
||||
voiceInputSupported: false
|
||||
}
|
||||
```
|
||||
|
||||
#### detail.inputType="time" && value="xxxx"
|
||||
|
||||
```js
|
||||
detail: {
|
||||
...
|
||||
inputType: "time"
|
||||
...
|
||||
type: "INPUT"
|
||||
...
|
||||
value: "10:14"
|
||||
}
|
||||
```
|
||||
|
||||
#### detail.inputType="date"
|
||||
|
||||
```js
|
||||
detail: {
|
||||
...
|
||||
inputType: "date"
|
||||
...
|
||||
type: "INPUT"
|
||||
}
|
||||
```
|
||||
|
||||
#### detail.inputType="date" && value="xxxx"
|
||||
|
||||
```js
|
||||
detail {
|
||||
...
|
||||
inputType: "date"
|
||||
...
|
||||
type: "INPUT"
|
||||
...
|
||||
value: "2016-05-20"
|
||||
}
|
||||
```
|
||||
|
||||
#### detail.type="datetime-local"
|
||||
|
||||
```
|
||||
detail {
|
||||
...
|
||||
inputType: "datetime-local"
|
||||
...
|
||||
type: "INPUT"
|
||||
}
|
||||
```
|
||||
|
||||
系统 UI 框架, 将先跳出选择日期选择窗, 再跳出选择时间窗.
|
||||
|
||||
#### [DEPRECATED]detail.type="datetime"
|
||||
|
||||
`<input type="datetime">` 已被废弃.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from './select.js'
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@star-web-components/select",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./select.js": {
|
||||
"default": "./select.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
import {css} from 'lit'
|
||||
|
||||
export default css`
|
||||
:host {
|
||||
display: block;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
a {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
font-size: var(--auto-26px);
|
||||
line-height: var(--auto-26px);
|
||||
color: var(--theme-blue);
|
||||
}
|
||||
|
||||
a::after {
|
||||
content: 'selector';
|
||||
font-family: 'star-icons';
|
||||
font-size: var(--auto-32px);
|
||||
min-width: var(--auto-32px); /* 应对可能的被挤压 */
|
||||
margin-left: var(--auto-14px);
|
||||
color: var(--selector-icon-color);
|
||||
}
|
||||
|
||||
:host([variant='rightarrow']) a::after {
|
||||
content: 'right-light';
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
select {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
::slotted(*) {
|
||||
display: none;
|
||||
}
|
||||
`
|
|
@ -0,0 +1,181 @@
|
|||
import {
|
||||
customElement,
|
||||
html,
|
||||
property,
|
||||
queryAssignedElements,
|
||||
state,
|
||||
CSSResult,
|
||||
StarBaseElement,
|
||||
} from '@star-web-components/base'
|
||||
import selectStyles from './select.css.js'
|
||||
import {StarSelectDialog} from '@star-web-components/dialog'
|
||||
import {StarLi} from '@star-web-components/li'
|
||||
import {StarRadio, StarRadioGroup} from '@star-web-components/radio'
|
||||
|
||||
export type RadioVariant = 'circle' | 'checkmark'
|
||||
|
||||
@customElement('star-select')
|
||||
export class StarSelect extends StarBaseElement {
|
||||
public static override get styles(): CSSResult {
|
||||
return selectStyles
|
||||
}
|
||||
|
||||
@property({type: String, reflect: true}) selected!: string
|
||||
|
||||
/* 提供给选择器窗的标题 */
|
||||
@property({type: String}) title!: string
|
||||
|
||||
@property({type: Boolean, reflect: true}) multiple = false
|
||||
|
||||
@property({type: Object}) data!: [
|
||||
[
|
||||
{
|
||||
label?: string
|
||||
value: string | number
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/* 用于指示自身风格,包括: selector(默认), rightarrow, */
|
||||
@property({type: String, reflect: true}) variant!: string
|
||||
|
||||
@state() label!: string
|
||||
|
||||
@queryAssignedElements() optionsSlot!: StarLi[]
|
||||
|
||||
/**
|
||||
* 兼容用户代理支持的分类选择器(带<optgroup>标签)
|
||||
*
|
||||
* 但预留分组.
|
||||
*/
|
||||
// a!: {
|
||||
// size?: number,
|
||||
// multiple?: string,
|
||||
// options: [
|
||||
// {
|
||||
// label: string
|
||||
// value: string | number
|
||||
// },
|
||||
// ] | [
|
||||
// {
|
||||
// optgroup:
|
||||
// }
|
||||
// ]
|
||||
|
||||
// }
|
||||
|
||||
protected firstUpdated(): void {
|
||||
// 1. 为 radio 标签,或是有实现类 radio 标签行为的标签
|
||||
// 如 <star-li type="radio">,<star-card type="radio">
|
||||
// 2. 不满足1的标签将被删除
|
||||
// 3. 如果option未指定label,将使用value值作为label值
|
||||
// 4. 将所有 option 的 checked 置为 false
|
||||
// 5. 如果是多值选择,设置 star-li 的 variant 属性为 "checkmark"
|
||||
if (this.optionsSlot.length === 0) throw new Error('No legal option')
|
||||
|
||||
for (const option of this.optionsSlot) {
|
||||
if (
|
||||
!(
|
||||
option instanceof StarRadio ||
|
||||
(option.type === 'radio' && option.value !== undefined)
|
||||
)
|
||||
) {
|
||||
option.parentElement?.removeChild(option)
|
||||
continue
|
||||
}
|
||||
|
||||
if (option.label === undefined) {
|
||||
option.label = option.value
|
||||
}
|
||||
if (this.multiple === true) {
|
||||
option.variant = 'checkmark'
|
||||
}
|
||||
option.checked = false
|
||||
}
|
||||
|
||||
// 当使用端未指定 selected 时,将进行如下行为:
|
||||
// 1. 使用 optionsSlot 中第一项的 value 和 label 作为默认值,
|
||||
// 当使用端指定了 selected 时,将进行如下行为:
|
||||
// 1. 遍历 optionsSlot 找到对等项
|
||||
// 当经历上述过程后,this.label 还为空,说明 this.selected 为错值
|
||||
// 那将继续使用 optionsSlot 中第一项的 value 和 label 作为默认值
|
||||
for (const [index, option] of this.optionsSlot.entries()) {
|
||||
if (this.selected !== undefined) {
|
||||
if (this.multiple === false) {
|
||||
if (this.selected === option.value) {
|
||||
this.label = option.label
|
||||
option.checked = true
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if (this.selected.split(',').includes(option.value)) {
|
||||
if (this.label === undefined) this.label = option.label
|
||||
else this.label += ',' + option.label
|
||||
option.checked = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (index === this.optionsSlot.length - 1) {
|
||||
if (this.selected === undefined || this.label === undefined) {
|
||||
console.warn('Not find a legal option, we will use the first option')
|
||||
|
||||
this.selected = this.optionsSlot[0].value
|
||||
this.label = this.optionsSlot[0].label
|
||||
this.optionsSlot[0].checked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件来源:star-radio-group 上的change自定义事件
|
||||
*/
|
||||
_onselect(e: Event) {
|
||||
const target = e.target as StarRadioGroup
|
||||
if (this.selected !== target.selected) {
|
||||
this.selected = target.getSelected()
|
||||
this.label = target.label
|
||||
this.emit('change')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当自身被点击时,打开 <select-dialog>,将 options 租借给它。
|
||||
* 完成调用后,<select-dialog> 再将 options 归还。
|
||||
*/
|
||||
_onclick(_: Event) {
|
||||
const starAlertDialog = new StarSelectDialog({
|
||||
title: this.title || '测试',
|
||||
type: 'select',
|
||||
multiple: this.multiple,
|
||||
cancel: '取消',
|
||||
confirm: '确定',
|
||||
onselect: this._onselect.bind(this),
|
||||
optionsSlot: this.optionsSlot,
|
||||
})
|
||||
// TODO: 移到overlay层
|
||||
document.body?.appendChild(starAlertDialog)
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<a>
|
||||
<span>${this.label}</span>
|
||||
</a>
|
||||
<slot><!-- 用于放置选择项option --></slot>
|
||||
`
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.addEventListener('click', this._onclick)
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'star-select': StarSelect
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'2g',
|
||||
'3g',
|
||||
'4g',
|
||||
'ip',
|
||||
'accessibility',
|
||||
'achievement',
|
||||
'add-contact',
|
||||
|
@ -18,8 +17,6 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'airplane',
|
||||
'alarm-clock-stop',
|
||||
'alarm-clock',
|
||||
'alarm-song-shock',
|
||||
'alarm-stop-shock',
|
||||
'alarm-stop',
|
||||
'alarm',
|
||||
'album',
|
||||
|
@ -48,6 +45,7 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'battery-7',
|
||||
'battery-8',
|
||||
'battery-9',
|
||||
'battery-capacity',
|
||||
'battery-charging',
|
||||
'battery-gray-1',
|
||||
'battery-gray',
|
||||
|
@ -83,6 +81,7 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'call',
|
||||
'callback-emergency',
|
||||
'camera-db',
|
||||
'camera-web',
|
||||
'camera',
|
||||
'change-wallpaper',
|
||||
'clear-input-left',
|
||||
|
@ -154,6 +153,7 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'incoming-sms',
|
||||
'info',
|
||||
'invisible',
|
||||
'ip',
|
||||
'keyboard-circle',
|
||||
'keyboard',
|
||||
'languages',
|
||||
|
@ -170,6 +170,7 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'media-mute',
|
||||
'media-sound',
|
||||
'media-storage',
|
||||
'memory',
|
||||
'menu',
|
||||
'message-voice',
|
||||
'message',
|
||||
|
@ -207,6 +208,7 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'power',
|
||||
'privacy',
|
||||
'qq',
|
||||
'ratio',
|
||||
'reboot',
|
||||
'recent-calls',
|
||||
'reduce-db',
|
||||
|
@ -217,12 +219,16 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'reply-all',
|
||||
'right-light',
|
||||
'right',
|
||||
'ring-mute-2',
|
||||
'ring-mute',
|
||||
'ring',
|
||||
'rocket',
|
||||
'rotate',
|
||||
'safe',
|
||||
'scene',
|
||||
'screen-projection',
|
||||
'screen-recording',
|
||||
'screen-size',
|
||||
'screen',
|
||||
'sd-card',
|
||||
'search',
|
||||
|
@ -230,6 +236,7 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'seek-back',
|
||||
'seek-forward',
|
||||
'select',
|
||||
'selector',
|
||||
'self-timer',
|
||||
'send-left',
|
||||
'send-right',
|
||||
|
@ -411,6 +418,8 @@ export class PanelFontsStarIcons extends LitElement {
|
|||
'update-balance',
|
||||
'usb',
|
||||
'user',
|
||||
'vibrate-and-ring-mute',
|
||||
'vibrate-and-ring',
|
||||
'vibrate',
|
||||
'video-mic',
|
||||
'video-size',
|
||||
|
|
|
@ -322,13 +322,7 @@ export class PanelLi extends LitElement {
|
|||
variant="circle"
|
||||
vertical
|
||||
>
|
||||
<star-card
|
||||
type="radio"
|
||||
label="浅色模式"
|
||||
variant="radio"
|
||||
value="light"
|
||||
checked
|
||||
>
|
||||
<star-card type="radio" label="浅色模式" value="light" checked>
|
||||
<star-svg-icon
|
||||
slot="image"
|
||||
style="width:var(--auto-208px);height:var(--auto-202px)"
|
||||
|
@ -336,7 +330,7 @@ export class PanelLi extends LitElement {
|
|||
${lightmode}
|
||||
</star-svg-icon>
|
||||
</star-card>
|
||||
<star-card type="radio" label="深色模式" variant="radio" value="dark">
|
||||
<star-card type="radio" label="深色模式" value="dark">
|
||||
<star-svg-icon
|
||||
slot="image"
|
||||
style="width:var(--auto-208px);height:var(--auto-202px)"
|
||||
|
|
|
@ -39,6 +39,7 @@ import './pattern-view/pattern-view'
|
|||
import './picker/picker'
|
||||
import './prompt/prompt'
|
||||
import './radio/radio'
|
||||
import './select/select'
|
||||
import './slider/slider'
|
||||
import './switch/switch'
|
||||
import './toast/toast'
|
||||
|
@ -100,6 +101,11 @@ export class PanelRoot extends LitElement {
|
|||
<star-ul type=${UlType.ONLY_HEADER} title="复合组件">
|
||||
<star-li label="StarLi-条目" icon="play-circle" href="#li"></star-li>
|
||||
<hr />
|
||||
<star-li
|
||||
label="StarSelect-选择器"
|
||||
icon="play-circle"
|
||||
href="#select"
|
||||
></star-li>
|
||||
</star-ul>
|
||||
|
||||
<star-ul type=${UlType.ONLY_HEADER} title="功能组件">
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
import {
|
||||
css,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
CSSResult,
|
||||
} from '@star-web-components/base'
|
||||
import '@star-web-components/select'
|
||||
import {lockscreen, lightmode, darkmode, weibo} from '../li/static/icons'
|
||||
|
||||
@customElement('panel-select')
|
||||
export class PanelSelect extends LitElement {
|
||||
render() {
|
||||
return html`
|
||||
<h1>star-select</h1>
|
||||
<div id="only-select">
|
||||
<star-select slot="select" selected="30" title="单值选择器">
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="60秒" value="60"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
|
||||
<star-select
|
||||
slot="select"
|
||||
selected="30"
|
||||
variant="rightarrow"
|
||||
title="单值选择器"
|
||||
>
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="60秒" value="60"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
|
||||
<star-select slot="select" selected="1800" title="时间选项">
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="45秒" value="45"></star-li>
|
||||
<star-li type="radio" label="1分钟" value="60"></star-li>
|
||||
<star-li type="radio" label="1分半钟" value="90"></star-li>
|
||||
<star-li type="radio" label="2分钟" value="120"></star-li>
|
||||
<star-li type="radio" label="3分钟" value="180"></star-li>
|
||||
<star-li type="radio" label="4分钟" value="240"></star-li>
|
||||
<star-li type="radio" label="5分钟" value="300"></star-li>
|
||||
<star-li type="radio" label="10分钟" value="600"></star-li>
|
||||
<star-li type="radio" label="15分钟" value="900"></star-li>
|
||||
<star-li type="radio" label="30分钟" value="1800"></star-li>
|
||||
<star-li type="radio" label="1小时" value="3600"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
</div>
|
||||
|
||||
<star-li type="selector" label="单值选择器(star-li)">
|
||||
<star-select
|
||||
slot="select"
|
||||
selected="30"
|
||||
title="时间选项"
|
||||
@change=${(e: any) => alert('selected is:' + e.target.selected)}
|
||||
>
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="60秒" value="60"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li
|
||||
type="selector"
|
||||
label="单值选择器(star-li[variant='rightarrow'])"
|
||||
>
|
||||
<star-select
|
||||
slot="select"
|
||||
selected="30"
|
||||
variant="rightarrow"
|
||||
title="时间选项"
|
||||
>
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="60秒" value="60"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li type="selector" label="单值选择器(不指定selected)">
|
||||
<star-select slot="select" title="时间选项">
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="60秒" value="60"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li type="selector" label="单值选择器(指定错误的selected)">
|
||||
<star-select slot="select" selected="0" title="时间选项">
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="60秒" value="60"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li type="selector" label="单值选择器(可滚动列表)">
|
||||
<star-select slot="select" selected="1800" title="时间选项">
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="45秒" value="45"></star-li>
|
||||
<star-li type="radio" label="1分钟" value="60"></star-li>
|
||||
<star-li type="radio" label="1分半钟" value="90"></star-li>
|
||||
<star-li type="radio" label="2分钟" value="120"></star-li>
|
||||
<star-li type="radio" label="3分钟" value="180"></star-li>
|
||||
<star-li type="radio" label="4分钟" value="240"></star-li>
|
||||
<star-li type="radio" label="5分钟" value="300"></star-li>
|
||||
<star-li type="radio" label="10分钟" value="600"></star-li>
|
||||
<star-li type="radio" label="15分钟" value="900"></star-li>
|
||||
<star-li type="radio" label="30分钟" value="1800"></star-li>
|
||||
<star-li type="radio" label="1小时" value="3600"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li type="selector" label="多值选择项">
|
||||
<star-select slot="select" selected="30" multiple title="时间选项">
|
||||
<star-li type="radio" label="15秒" value="15"></star-li>
|
||||
<star-li type="radio" label="30秒" value="30"></star-li>
|
||||
<star-li type="radio" label="60秒" value="60"></star-li>
|
||||
<star-li type="radio" label="永不" value="never"></star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li type="selector" label="多值选择项">
|
||||
<star-select
|
||||
slot="select"
|
||||
selected="two,three"
|
||||
multiple
|
||||
title="操作选项"
|
||||
>
|
||||
<star-li type="radio" label="操作一" value="one"></star-li>
|
||||
<star-li type="radio" label="操作二" value="two"></star-li>
|
||||
<star-li type="radio" label="操作三" value="three"></star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li type="selector" label="复杂选择项(star-li)">
|
||||
<star-select slot="select" selected="transfer-photo" title="传输选项">
|
||||
<star-li type="radio" label="传输文件" value="transfer-file">
|
||||
<star-svg-icon slot="icon">${lockscreen}</star-svg-icon>
|
||||
</star-li>
|
||||
<star-li type="radio" label="传输照片" value="transfer-photo">
|
||||
<star-svg-icon slot="icon">${lockscreen}</star-svg-icon>
|
||||
</star-li>
|
||||
<star-li type="radio" label="仅充电" value="only-charge">
|
||||
<star-svg-icon slot="icon">${lockscreen}</star-svg-icon>
|
||||
</star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li type="selector" label="复杂选择项(star-card)">
|
||||
<star-select
|
||||
slot="select"
|
||||
selected="transfer-photo"
|
||||
title="浅色和深色模式切换"
|
||||
>
|
||||
<star-card type="radio" label="浅色模式" value="light" checked>
|
||||
<star-svg-icon
|
||||
slot="image"
|
||||
style="width:var(--auto-208px);height:var(--auto-202px)"
|
||||
>
|
||||
${lightmode}
|
||||
</star-svg-icon>
|
||||
</star-card>
|
||||
<star-card type="radio" label="深色模式" value="dark">
|
||||
<star-svg-icon
|
||||
slot="image"
|
||||
style="width:var(--auto-208px);height:var(--auto-202px)"
|
||||
>
|
||||
${darkmode}
|
||||
</star-svg-icon>
|
||||
</star-card>
|
||||
</star-select>
|
||||
</star-li>
|
||||
|
||||
<star-li type="selector" label="复杂单值选择器(star-li)">
|
||||
<star-select
|
||||
slot="select"
|
||||
selected="transfer-photo"
|
||||
title="浅色和深色模式切换"
|
||||
>
|
||||
<star-li
|
||||
type="radio"
|
||||
label="日出到日落"
|
||||
value="natural"
|
||||
square="2.4G/5G"
|
||||
description="根据所在地的日出和日落时间,自动切换浅色和深色模式"
|
||||
>
|
||||
<star-svg-icon slot="icon">${weibo}</star-svg-icon>
|
||||
</star-li>
|
||||
<star-li
|
||||
type="radio"
|
||||
label="自定义时间"
|
||||
value="customize"
|
||||
square="2.4G/5G"
|
||||
description="根据设置的时间段,自动切换浅色和深色模式"
|
||||
>
|
||||
<star-svg-icon slot="icon">${weibo}</star-svg-icon>
|
||||
</star-li>
|
||||
</star-select>
|
||||
</star-li>
|
||||
`
|
||||
}
|
||||
public static override get styles(): CSSResult {
|
||||
return css``
|
||||
}
|
||||
}
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'panel-select': PanelSelect
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue