bug fix and performance improvements

This commit is contained in:
quantulr
2023-08-18 17:32:18 +08:00
parent 3c6ab550cf
commit e750b9be9c
923 changed files with 46650 additions and 9 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
:: BASE_DOC ::
## API
### ActionSheet Props
name | type | default | description | required
-- | -- | -- | -- | --
align | String | center | `0.29.0`。optionscenter/left | N
cancel-text | String | - | \- | N
count | Number | 8 | \- | N
description | String | - | `0.29.0` | N
items | Array | - | required。Typescript`Array<string \| ActionSheetItem>` `interface ActionSheetItem {label: string; color?: string; disabled?: boolean }`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/action-sheet/type.ts) | Y
show-cancel | Boolean | true | \- | N
show-overlay | Boolean | true | \- | N
theme | String | list | optionslist/grid | N
visible | Boolean | false | required | Y
default-visible | Boolean | undefined | required。uncontrolled property | Y
### ActionSheet Events
name | params | description
-- | -- | --
cancel | \- | \-
close | `(trigger: TriggerSource)` | [see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/action-sheet/type.ts)。<br/>`type TriggerSource = 'overlay' \| 'command' \| 'select' `<br/>
selected | `(selected: ActionSheetItem \| string, index: number)` | \-
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-action-sheet-border-color | @gray-color-1 | -
--td-action-sheet-border-radius | @radius-extra-large | -
--td-action-sheet-cancel-color | @font-gray-1 | -
--td-action-sheet-cancel-height | 96rpx | -
--td-action-sheet-color | @font-gray-1 | -
--td-action-sheet-description-color | @font-gray-3 | -
--td-action-sheet-list-item-disabled-color | @font-gray-4 | -
--td-action-sheet-list-item-height | 112rpx | -
--td-action-sheet-text-align | center | -

View File

@ -0,0 +1,128 @@
---
title: ActionSheet 动作面板
description: 由用户操作后触发的一种特定的模态弹出框 ,呈现一组与当前情境相关的两个或多个选项。
spline: data
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-89%25-blue" /></span>
<div style="background: #ecf2fe; display: flex; align-items: center; line-height: 20px; padding: 14px 24px; border-radius: 3px; color: #555a65">
<svg fill="none" viewBox="0 0 16 16" width="16px" height="16px" style="margin-right: 5px">
<path fill="#0052d9" d="M8 15A7 7 0 108 1a7 7 0 000 14zM7.4 4h1.2v1.2H7.4V4zm.1 2.5h1V12h-1V6.5z" fillOpacity="0.9"></path>
</svg>
该组件于 0.9.0 版本上线,请留意版本。
</div>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-action-sheet": "tdesign-miniprogram/action-sheet/action-sheet",
}
```
## 代码演示
### 组件类型
列表型动作面板
{{ list }}
宫格型动作面板
{{ grid }}
### 组件状态
宫格型动作面板
{{ status }}
### 组件样式
列表型对齐方式
{{ align }}
### 支持指令调用
```javascript
import ActionSheet, { ActionSheetTheme } from 'tdesign-miniprogram/action-sheet/index';
// 指令调用不同于组件引用不需要传入visible
const basicListOption: ActionSheetShowOption = {
theme: ActionSheetTheme.List,
selector: '#t-action-sheet',
items: [
{
label: '默认选项',
},
{
label: '失效选项',
disabled: true,
},
{
label: '警告选项',
color: '#e34d59',
},
],
};
const handler = ActionSheet.show(basicListOption);
```
指令调用的关闭如下
```javascript
handler.close();
```
## API
### ActionSheet Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
align | String | center | `0.29.0`。水平对齐方式。可选项center/left | N
cancel-text | String | - | 设置取消按钮的文本 | N
count | Number | 8 | 设置每页展示菜单的数量,仅当 type=grid 时有效 | N
description | String | - | `0.29.0`。动作面板描述文字 | N
items | Array | - | 必需。菜单项。TS 类型:`Array<string \| ActionSheetItem>` `interface ActionSheetItem {label: string; color?: string; disabled?: boolean }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/action-sheet/type.ts) | Y
show-cancel | Boolean | true | 是否显示取消按钮 | N
show-overlay | Boolean | true | 是否显示遮罩层 | N
theme | String | list | 展示类型列表和表格形式展示。可选项list/grid | N
visible | Boolean | false | 必需。显示与隐藏 | Y
default-visible | Boolean | undefined | 必需。显示与隐藏。非受控属性 | Y
### ActionSheet Events
名称 | 参数 | 描述
-- | -- | --
cancel | \- | 点击取消按钮时触发
close | `(trigger: TriggerSource)` | 关闭时触发。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/action-sheet/type.ts)。<br/>`type TriggerSource = 'overlay' \| 'command' \| 'select' `<br/>
selected | `(selected: ActionSheetItem \| string, index: number)` | 选择菜单项时触发
### ActionSheet 外部样式类
类名 | 说明
-- | --
t-class | 根节点样式类
t-class-content | 内容样式类
t-class-cancel | 取消样式类
### CSS 变量
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-action-sheet-border-color | @gray-color-1 | -
--td-action-sheet-border-radius | @radius-extra-large | -
--td-action-sheet-cancel-color | @font-gray-1 | -
--td-action-sheet-cancel-height | 96rpx | -
--td-action-sheet-color | @font-gray-1 | -
--td-action-sheet-description-color | @font-gray-3 | -
--td-action-sheet-list-item-disabled-color | @font-gray-4 | -
--td-action-sheet-list-item-height | 112rpx | -
--td-action-sheet-text-align | center | -

View File

@ -0,0 +1,76 @@
import { SuperComponent } from '../common/src/index';
export default class ActionSheet extends SuperComponent {
static show: (options: import("./show").ActionSheetShowOption) => WechatMiniprogram.Component.TrivialInstance;
externalClasses: string[];
properties: {
align?: {
type: StringConstructor;
value?: "center" | "left";
};
cancelText?: {
type: StringConstructor;
value?: string;
};
count?: {
type: NumberConstructor;
value?: number;
};
description?: {
type: StringConstructor;
value?: string;
};
items: {
type: ArrayConstructor;
value?: (string | import("./type").ActionSheetItem)[];
};
showCancel?: {
type: BooleanConstructor;
value?: boolean;
};
theme?: {
type: StringConstructor;
value?: "list" | "grid";
};
visible: {
type: BooleanConstructor;
value?: boolean;
};
defaultVisible: {
type: BooleanConstructor;
value?: boolean;
};
showOverlay: {
type: BooleanConstructor;
value?: boolean;
};
popupProps: {
type: ObjectConstructor;
value?: object;
};
};
data: {
prefix: string;
classPrefix: string;
gridThemeItems: any[];
currentSwiperIndex: number;
defaultPopUpProps: {};
defaultPopUpzIndex: number;
};
controlledProps: {
key: string;
event: string;
}[];
ready(): void;
methods: {
onSwiperChange(e: WechatMiniprogram.TouchEvent): void;
splitGridThemeActions(): void;
show(options: any): void;
memoInitialData(): void;
close(): void;
onPopupVisibleChange({ detail }: {
detail: any;
}): void;
onSelect(event: WechatMiniprogram.TouchEvent): void;
onCancel(): void;
};
}

View File

@ -0,0 +1,102 @@
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 { chunk } from '../common/utils';
import { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import { ActionSheetTheme, show } from './show';
import props from './props';
const { prefix } = config;
const name = `${prefix}-action-sheet`;
let ActionSheet = class ActionSheet extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`, `${prefix}-class-content`, `${prefix}-class-cancel`];
this.properties = Object.assign({}, props);
this.data = {
prefix,
classPrefix: name,
gridThemeItems: [],
currentSwiperIndex: 0,
defaultPopUpProps: {},
defaultPopUpzIndex: 11500,
};
this.controlledProps = [
{
key: 'visible',
event: 'visible-change',
},
];
this.methods = {
onSwiperChange(e) {
const { detail: { current }, } = e;
this.setData({
currentSwiperIndex: current,
});
},
splitGridThemeActions() {
if (this.data.theme !== ActionSheetTheme.Grid)
return;
this.setData({
gridThemeItems: chunk(this.data.items, this.data.count),
});
},
show(options) {
this.setData(Object.assign(Object.assign(Object.assign({}, this.initialData), options), { visible: true }));
this.splitGridThemeActions();
this.autoClose = true;
this._trigger('visible-change', { visible: true });
},
memoInitialData() {
this.initialData = Object.assign(Object.assign({}, this.properties), this.data);
},
close() {
this.triggerEvent('close', { trigger: 'command' });
this._trigger('visible-change', { visible: false });
},
onPopupVisibleChange({ detail }) {
if (!detail.visible) {
this.triggerEvent('close', { trigger: 'overlay' });
this._trigger('visible-change', { visible: false });
}
if (this.autoClose) {
this.setData({ visible: false });
this.autoClose = false;
}
},
onSelect(event) {
const { currentSwiperIndex, items, gridThemeItems, count, theme } = this.data;
const { index } = event.currentTarget.dataset;
const isSwiperMode = theme === ActionSheetTheme.Grid;
const item = isSwiperMode ? gridThemeItems[currentSwiperIndex][index] : items[index];
const realIndex = isSwiperMode ? index + currentSwiperIndex * count : index;
if (item) {
this.triggerEvent('selected', { selected: item, index: realIndex });
if (!item.disabled) {
this.triggerEvent('close', { trigger: 'select' });
this._trigger('visible-change', { visible: false });
}
}
},
onCancel() {
this.triggerEvent('cancel');
if (this.autoClose) {
this.setData({ visible: false });
this.autoClose = false;
}
},
};
}
ready() {
this.memoInitialData();
this.splitGridThemeActions();
}
};
ActionSheet.show = show;
ActionSheet = __decorate([
wxComponent()
], ActionSheet);
export default ActionSheet;

View File

@ -0,0 +1,10 @@
{
"component": true,
"usingComponents": {
"t-icon": "../icon/icon",
"t-popup": "../popup/popup",
"t-grid": "../grid/grid",
"t-grid-item": "../grid-item/grid-item",
"t-swiper-nav": "../swiper-nav/swiper-nav"
}
}

View File

@ -0,0 +1,48 @@
<wxs src="./action-sheet.wxs" module="this" />
<wxs src="../common/utils.wxs" module="_" />
<import src="./template/list.wxml" />
<import src="./template/grid.wxml" />
<view id="{{classPrefix}}" style="{{_._style([style, customStyle])}}" class="{{classPrefix}} class {{prefix}}-class">
<t-popup
visible="{{visible}}"
placement="bottom"
bind:visible-change="onPopupVisibleChange"
show-overlay="{{showOverlay}}"
z-index="{{ popupProps.zIndex || defaultPopUpzIndex }}"
overlay-props="{{ popupProps.overlayProps || defaultPopUpProps }}"
>
<view
class="{{_.cls(classPrefix + '__content', [['grid', gridThemeItems.length]])}} {{prefix}}-class-content"
tabindex="0"
>
<view wx:if="{{description}}" tabindex="0" class="{{_.cls(classPrefix + '__description', [align])}}"
>{{description}}</view
>
<block wx:if="{{gridThemeItems.length}}">
<template is="grid" data="{{classPrefix, prefix, gridThemeItems, count, currentSwiperIndex}}" />
</block>
<view wx:elif="{{items && items.length}}" class="{{classPrefix}}__list">
<block wx:for="{{ items }}" wx:key="index">
<template
is="list"
data="{{index, classPrefix, listThemeItemClass: _.cls(classPrefix + '__list-item', [align, [disabled, item.disabled]]), item}}"
/>
</block>
</view>
</view>
<slot />
<view wx:if="{{showCancel}}" class="{{classPrefix}}__footer">
<view class="{{classPrefix}}__gap-{{theme}}" />
<view
class="{{classPrefix}}__cancel {{prefix}}-class-cancel"
hover-class="{{classPrefix}}__cancel--hover"
hover-stay-time="70"
bind:tap="onCancel"
aria-role="button"
>
{{ cancelText }}
</view>
</view>
</t-popup>
</view>

View File

@ -0,0 +1,19 @@
var getListThemeItemClass = function (props) {
var classPrefix = props.classPrefix;
var item = props.item;
var prefix = props.prefix;
var classList = [classPrefix + '__list-item'];
if (item.disabled) {
classList.push(prefix + '-is-disabled');
}
return classList.join(' ');
};
var isImage = function (name) {
return name.indexOf('/') !== -1;
};
module.exports = {
getListThemeItemClass: getListThemeItemClass,
isImage: isImage,
};

View File

@ -0,0 +1,169 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-action-sheet__content {
color: var(--td-action-sheet-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
border-top-left-radius: var(--td-action-sheet-border-radius, var(--td-radius-extra-large, 24rpx));
border-top-right-radius: var(--td-action-sheet-border-radius, var(--td-radius-extra-large, 24rpx));
background-color: var(--td-bg-color-container, var(--td-font-white-1, #ffffff));
overflow: hidden;
}
.t-action-sheet__content--grid {
padding-top: 16rpx;
}
.t-action-sheet__content:focus {
outline: 0;
}
.t-action-sheet__grid {
padding-bottom: 16rpx;
}
.t-action-sheet__grid--swiper {
padding-bottom: 48rpx;
}
.t-action-sheet__description {
color: var(--td-action-sheet-description-color, var(--td-font-gray-3, rgba(0, 0, 0, 0.4)));
line-height: 44rpx;
font-size: 28rpx;
text-align: var(--td-action-sheet-text-align, center);
padding: 24rpx 32rpx;
position: relative;
}
.t-action-sheet__description:focus {
outline: 0;
}
.t-action-sheet__description::after {
content: '';
display: block;
position: absolute;
top: unset;
bottom: 0;
left: unset;
right: unset;
background-color: var(--td-action-sheet-border-color, var(--td-gray-color-1, #f3f3f3));
}
.t-action-sheet__description::after {
height: 1px;
left: 0;
right: 0;
transform: scaleY(0.5);
}
.t-action-sheet__description--left {
text-align: left;
}
.t-action-sheet__description--left::after {
left: 32rpx;
}
.t-action-sheet__list-item {
display: flex;
align-items: center;
justify-content: center;
position: relative;
height: var(--td-action-sheet-list-item-height, 112rpx);
padding: 0 32rpx;
}
.t-action-sheet__list-item::after {
content: '';
display: block;
position: absolute;
top: unset;
bottom: 0;
left: unset;
right: unset;
background-color: var(--td-action-sheet-border-color, var(--td-gray-color-1, #f3f3f3));
}
.t-action-sheet__list-item::after {
height: 1px;
left: 0;
right: 0;
transform: scaleY(0.5);
}
.t-action-sheet__list-item:focus {
outline: 0;
}
.t-action-sheet__list-item--left {
justify-content: start;
}
.t-action-sheet__list-item--left::after {
left: 32rpx;
}
.t-action-sheet__list-item--disabled {
color: var(--td-action-sheet-list-item-disabled-color, var(--td-font-gray-4, rgba(0, 0, 0, 0.26)));
}
.t-action-sheet__list-item-text {
font-size: var(--td-font-size-m, 32rpx);
word-wrap: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.t-action-sheet__list-item-icon {
margin-right: 16rpx;
}
.t-action-sheet__list-item-icon--suffix {
margin-left: auto;
}
.t-action-sheet__swiper-wrap {
margin-top: 8rpx;
position: relative;
}
.t-action-sheet__footer {
background-color: var(--td-bg-color-container, var(--td-font-white-1, #ffffff));
}
.t-action-sheet__gap-list {
height: 16rpx;
background-color: var(--td-action-sheet-border-color, var(--td-gray-color-1, #f3f3f3));
}
.t-action-sheet__gap-grid {
height: 1rpx;
background-color: var(--td-action-sheet-border-color, var(--td-gray-color-1, #f3f3f3));
}
.t-action-sheet__cancel {
display: flex;
align-items: center;
justify-content: center;
color: var(--td-action-sheet-cancel-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
height: var(--td-action-sheet-cancel-height, 96rpx);
}
.t-action-sheet__dots {
position: absolute;
left: 50%;
bottom: 32rpx;
transform: translateX(-50%);
display: flex;
flex-direction: row;
}
.t-action-sheet__dots-item {
width: 16rpx;
height: 16rpx;
background-color: #dcdcdc;
border-radius: 50%;
margin: 0 16rpx;
transition: all 0.4s ease-in;
}
.t-action-sheet__dots-item.t-is-active {
background-color: #0052d9;
}

View File

@ -0,0 +1,8 @@
/// <reference types="miniprogram-api-typings" />
import { ActionSheetItem, ActionSheetTheme, ActionSheetShowOption } from './show';
export { ActionSheetItem, ActionSheetTheme, ActionSheetShowOption };
declare const _default: {
show(options: ActionSheetShowOption): WechatMiniprogram.Component.TrivialInstance;
close(options: ActionSheetShowOption): void;
};
export default _default;

View File

@ -0,0 +1,10 @@
import { show, close, ActionSheetTheme } from './show';
export { ActionSheetTheme };
export default {
show(options) {
return show(options);
},
close(options) {
return close(options);
},
};

View File

@ -0,0 +1,3 @@
import { TdActionSheetProps } from './type';
declare const props: TdActionSheetProps;
export default props;

View File

@ -0,0 +1,46 @@
const props = {
align: {
type: String,
value: 'center',
},
cancelText: {
type: String,
value: '取消',
},
count: {
type: Number,
value: 8,
},
description: {
type: String,
value: '',
},
items: {
type: Array,
},
showCancel: {
type: Boolean,
value: true,
},
theme: {
type: String,
value: 'list',
},
visible: {
type: Boolean,
value: null,
},
defaultVisible: {
type: Boolean,
value: false,
},
showOverlay: {
type: Boolean,
value: true,
},
popupProps: {
type: Object,
value: {},
},
};
export default props;

View File

@ -0,0 +1,31 @@
/// <reference types="miniprogram-api-typings" />
/// <reference types="miniprogram-api-typings" />
export interface ActionSheetItem {
label: string;
color?: string;
disabled?: boolean;
icon?: string;
}
declare type Context = WechatMiniprogram.Page.TrivialInstance | WechatMiniprogram.Component.TrivialInstance;
export declare enum ActionSheetTheme {
List = "list",
Grid = "grid"
}
interface ActionSheetProps {
align: 'center' | 'left';
cancelText?: string;
count?: number;
description: string;
items: Array<string | ActionSheetItem>;
showCancel?: boolean;
theme?: ActionSheetTheme;
visible: boolean;
defaultVisible?: boolean;
}
export interface ActionSheetShowOption extends Omit<ActionSheetProps, 'visible'> {
context?: Context;
selector?: string;
}
export declare const show: (options: ActionSheetShowOption) => WechatMiniprogram.Component.TrivialInstance;
export declare const close: (options: ActionSheetShowOption) => void;
export {};

View File

@ -0,0 +1,33 @@
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { getInstance } from '../common/utils';
export var ActionSheetTheme;
(function (ActionSheetTheme) {
ActionSheetTheme["List"] = "list";
ActionSheetTheme["Grid"] = "grid";
})(ActionSheetTheme || (ActionSheetTheme = {}));
export const show = function (options) {
const _a = Object.assign({}, options), { context, selector = '#t-action-sheet' } = _a, otherOptions = __rest(_a, ["context", "selector"]);
const instance = getInstance(context, selector);
if (instance) {
instance.show(Object.assign({}, otherOptions));
return instance;
}
console.error('未找到组件,请确认 selector && context 是否正确');
};
export const close = function (options) {
const { context, selector = '#t-action-sheet' } = Object.assign({}, options);
const instance = getInstance(context, selector);
if (instance) {
instance.close();
}
};

View File

@ -0,0 +1,51 @@
<template name="grid">
<block wx:if="{{gridThemeItems.length === 1}}">
<t-grid align="center" t-class="{{classPrefix}}__grid" column="{{count / 2}}" class="{{classPrefix}}__single-wrap">
<t-grid-item
t-class="{{classPrefix}}__grid-item"
class="{{classPrefix}}__square"
wx:for="{{gridThemeItems[0]}}"
wx:key="index"
bind:tap="onSelect"
data-index="{{index}}"
icon="{{ { name: item.icon, color: item.color } }}"
text="{{item.label}}"
image="{{item.image}}"
style="--td-grid-item-text-color: {{item.color}}"
>
</t-grid-item>
</t-grid>
</block>
<block wx:elif="{{gridThemeItems.length > 1}}">
<view class="{{classPrefix}}__swiper-wrap">
<swiper style="height: 456rpx" autoplay="{{false}}" current="{{currentSwiperIndex}}" bindchange="onSwiperChange">
<swiper-item wx:for="{{gridThemeItems}}" wx:key="index">
<t-grid align="center" t-class="{{classPrefix}}__grid {{classPrefix}}__grid--swiper" column="{{count / 2}}">
<t-grid-item
t-class="{{classPrefix}}__grid-item"
class="{{classPrefix}}__square"
wx:for="{{item}}"
wx:key="index"
data-index="{{index}}"
bind:tap="onSelect"
icon="{{ { name: item.icon, color: item.color } }}"
text="{{item.label}}"
image="{{item.image}}"
style="--td-grid-item-text-color: {{item.color}}"
>
</t-grid-item>
</t-grid>
</swiper-item>
</swiper>
<view class="{{classPrefix}}__nav">
<view class="{{classPrefix}}__dots">
<view
wx:for="{{gridThemeItems.length}}"
wx:key="index"
class="{{classPrefix}}__dots-item {{index === currentSwiperIndex ? prefix + '-is-active' : ''}}"
/>
</view>
</view>
</view>
</block>
</template>

View File

@ -0,0 +1,20 @@
<template name="list">
<view
data-index="{{index}}"
style="{{ item.color ? 'color: ' + item.color : '' }}"
class="{{listThemeItemClass}}"
bind:tap="onSelect"
aria-role="{{ariaRole || 'button'}}"
aria-label="{{item.label || item}}"
tabindex="0"
>
<t-icon wx:if="{{item.icon}}" name="{{item.icon}}" class="{{classPrefix}}__list-item-icon" size="48rpx"></t-icon>
<view class="{{classPrefix}}__list-item-text">{{item.label || item}}</view>
<t-icon
wx:if="{{item.suffixIcon}}"
name="{{item.suffixIcon}}"
class="{{classPrefix}}__list-item-icon {{classPrefix}}__list-item-icon--suffix"
size="48rpx"
></t-icon>
</view>
</template>

View File

@ -0,0 +1,53 @@
export interface TdActionSheetProps {
align?: {
type: StringConstructor;
value?: 'center' | 'left';
};
cancelText?: {
type: StringConstructor;
value?: string;
};
count?: {
type: NumberConstructor;
value?: number;
};
description?: {
type: StringConstructor;
value?: string;
};
items: {
type: ArrayConstructor;
value?: Array<string | ActionSheetItem>;
};
showCancel?: {
type: BooleanConstructor;
value?: boolean;
};
theme?: {
type: StringConstructor;
value?: 'list' | 'grid';
};
visible: {
type: BooleanConstructor;
value?: boolean;
};
defaultVisible: {
type: BooleanConstructor;
value?: boolean;
};
showOverlay: {
type: BooleanConstructor;
value?: boolean;
};
popupProps: {
type: ObjectConstructor;
value?: object;
};
}
export interface ActionSheetItem {
label: string;
color?: string;
disabled?: boolean;
icon?: string;
suffixIcon?: string;
}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,28 @@
import { SuperComponent, RelationsOptions } from '../common/src/index';
export default class AvatarGroup extends SuperComponent {
externalClasses: string[];
properties: import("./type").TdAvatarGroupProps;
data: {
prefix: string;
classPrefix: string;
hasChild: boolean;
length: number;
className: string;
};
options: {
multipleSlots: boolean;
};
relations: RelationsOptions;
lifetimes: {
attached(): void;
ready(): void;
};
observers: {
'cascading, size'(): void;
};
methods: {
setClass(): void;
handleMax(): void;
handleChildCascading(): void;
};
}

View File

@ -0,0 +1,86 @@
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 { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import avatarGroupProps from './props';
const { prefix } = config;
const name = `${prefix}-avatar-group`;
let AvatarGroup = class AvatarGroup extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`, `${prefix}-class-content`, `${prefix}-class-image`];
this.properties = avatarGroupProps;
this.data = {
prefix,
classPrefix: name,
hasChild: true,
length: 0,
className: '',
};
this.options = {
multipleSlots: true,
};
this.relations = {
'../avatar/avatar': {
type: 'descendant',
},
};
this.lifetimes = {
attached() {
this.setClass();
},
ready() {
this.setData({
length: this.$children.length,
});
this.handleMax();
this.handleChildCascading();
},
};
this.observers = {
'cascading, size'() {
this.setClass();
},
};
this.methods = {
setClass() {
const { cascading, size } = this.properties;
const direction = cascading.split('-')[0];
const classList = [
name,
`${prefix}-class`,
`${name}-offset-${direction}-${size.indexOf('px') > -1 ? 'medium' : size}`,
];
this.setData({
className: classList.join(' '),
});
},
handleMax() {
const { max } = this.data;
const len = this.$children.length;
if (!max || max > len)
return;
const restAvatars = this.$children.splice(max, len - max);
restAvatars.forEach((child) => {
child.hide();
});
},
handleChildCascading() {
if (this.properties.cascading === 'right-up')
return;
const defaultZIndex = 100;
this.$children.forEach((child, index) => {
child.updateCascading(defaultZIndex - index * 10);
});
},
};
}
};
AvatarGroup = __decorate([
wxComponent()
], AvatarGroup);
export default AvatarGroup;

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"t-avatar": "../avatar/avatar"
}
}

View File

@ -0,0 +1,20 @@
<wxs src="../common/utils.wxs" module="_" />
<view style="{{_._style([style, customStyle])}}" class="{{className}} class">
<slot />
<!-- 自定义折叠元素 -->
<view class="{{classPrefix}}__collapse--slot">
<slot name="collapse-avatar" />
</view>
<!-- 默认折叠元素 -->
<view class="{{classPrefix}}__collapse--default" wx:if="{{max && (max < length)}}">
<t-avatar
t-class-image="{{prefix}}-avatar--border {{prefix}}-avatar--border-{{size}} {{prefix}}-class-image"
t-class-content="{{prefix}}-class-content"
size="{{size}}"
icon="{{ collapseAvatar ? '' : 'user-add'}}"
aria-role="none"
>{{collapseAvatar}}</t-avatar
>
</view>
</view>

View File

@ -0,0 +1,137 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-avatar {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
background-color: var(--td-avatar-bg-color, var(--td-brand-color-light-active, var(--td-primary-color-2, #d9e1ff)));
color: var(--td-avatar-content-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-avatar__wrapper {
display: inline-flex;
position: relative;
vertical-align: top;
margin-left: var(--td-avatar-margin-left, 0);
}
.t-avatar--large {
width: var(--td-avatar-large-width, 128rpx);
height: var(--td-avatar-large-width, 128rpx);
font-size: var(--td-avatar-text-large-font-size, 16px);
}
.t-avatar--large .t-avatar__icon {
font-size: var(--td-avatar-icon-large-font-size, 64rpx);
}
.t-avatar--medium {
width: var(--td-avatar-medium-width, 96rpx);
height: var(--td-avatar-medium-width, 96rpx);
font-size: var(--td-avatar-text-medium-font-size, var(--td-font-size-base, 28rpx));
}
.t-avatar--medium .t-avatar__icon {
font-size: var(--td-avatar-icon-medium-font-size, 48rpx);
}
.t-avatar--small {
width: var(--td-avatar-small-width, 80rpx);
height: var(--td-avatar-small-width, 80rpx);
font-size: var(--td-avatar-text-small-font-size, var(--td-font-size-s, 24rpx));
}
.t-avatar--small .t-avatar__icon {
font-size: var(--td-avatar-icon-small-font-size, 40rpx);
}
.t-avatar .t-image,
.t-avatar__image {
width: 100%;
height: 100%;
}
.t-avatar--circle {
border-radius: var(--td-avatar-circle-border-radius, var(--td-radius-circle, 50%));
overflow: hidden;
}
.t-avatar--round {
border-radius: var(--td-avatar-round-border-radius, var(--td-radius-default, 12rpx));
overflow: hidden;
}
.t-avatar__text,
.t-avatar__icon {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.t-avatar__text:empty,
.t-avatar__icon:empty {
width: 0;
height: 0;
}
.t-avatar--border {
border-color: var(--td-avatar-border-color, #fff);
border-style: solid;
}
.t-avatar--border-small {
border-width: var(--td-avatar-border-width-small, 4rpx);
}
.t-avatar--border-medium {
border-width: var(--td-avatar-border-width-medium, 6rpx);
}
.t-avatar--border-large {
border-width: var(--td-avatar-border-width-large, 8rpx);
}
.t-avatar-group {
display: inline-flex;
align-items: center;
}
.t-avatar-group-offset-left-small {
--td-avatar-margin-left: var(--td-avatar-group-margin-left-small, -4px);
}
.t-avatar-group-offset-left-medium {
--td-avatar-margin-left: var(--td-avatar-group-margin-left-medium, -6px);
}
.t-avatar-group-offset-left-large {
--td-avatar-margin-left: var(--td-avatar-group-margin-left-large, -8px);
}
.t-avatar-group-offset-right-small {
--td-avatar-margin-left: var(--td-avatar-group-margin-left-small, -4px);
}
.t-avatar-group-offset-right-medium {
--td-avatar-margin-left: var(--td-avatar-group-margin-left-medium, -6px);
}
.t-avatar-group-offset-right-large {
--td-avatar-margin-left: var(--td-avatar-group-margin-left-large, -8px);
}
.t-avatar-group__collapse--slot {
float: left;
}
.t-avatar-group__collapse--slot:not(:empty) + .t-avatar-group__collapse--default {
display: none;
float: left;
}
.t-avatar-group__collapse--slot:empty + .t-avatar-group__collapse--default {
display: block;
float: left;
}

View File

@ -0,0 +1,3 @@
import { TdAvatarGroupProps } from './type';
declare const props: TdAvatarGroupProps;
export default props;

View File

@ -0,0 +1,20 @@
const props = {
cascading: {
type: String,
value: 'left-up',
},
collapseAvatar: {
type: String,
},
externalClasses: {
type: Array,
},
max: {
type: Number,
},
size: {
type: String,
value: 'medium',
},
};
export default props;

View File

@ -0,0 +1,27 @@
export interface TdAvatarGroupProps {
cascading?: {
type: StringConstructor;
value?: CascadingValue;
};
collapseAvatar?: {
type: StringConstructor;
value?: string;
};
style?: {
type: StringConstructor;
value?: string;
};
externalClasses?: {
type: ArrayConstructor;
value?: ['t-class', 't-class-image', 't-class-content'];
};
max?: {
type: NumberConstructor;
value?: number;
};
size?: {
type: StringConstructor;
value?: string;
};
}
export declare type CascadingValue = 'left-up' | 'right-up';

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,60 @@
:: BASE_DOC ::
## API
### Avatar Props
name | type | default | description | required
-- | -- | -- | -- | --
alt | String | - | show it when url is not valid | N
badge-props | Object | - | Typescript`BadgeProps`[Badge API Documents](./badge?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar/type.ts) | N
bordered | Boolean | false | \- | N
external-classes | Array | - | `['t-class', 't-class-image', 't-class-icon', 't-class-alt', 't-class-content']` | N
hide-on-load-failed | Boolean | false | hide image when loading image failed | N
icon | String / Object | - | \- | N
image | String | - | images url | N
image-props | Object | - | \- | N
shape | String | circle | shape。optionscircle/round。Typescript`ShapeEnum ` `type ShapeEnum = 'circle' \| 'round'`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar/type.ts) | N
size | String | medium | size | N
### Avatar Events
name | params | description
-- | -- | --
error | \- | trigger on image load failed
### AvatarGroup Props
name | type | default | description | required
-- | -- | -- | -- | --
cascading | String | 'right-up' | multiple images cascading。optionsleft-up/right-up。Typescript`CascadingValue` `type CascadingValue = 'left-up' \| 'right-up'`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar-group/type.ts) | N
collapse-avatar | String / Slot | - | \- | N
external-classes | Array | - | `['t-class', 't-class-image', 't-class-content']` | N
max | Number | - | \- | N
size | String | medium | size | N
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-avatar-group-margin-left-large | -8px | -
--td-avatar-group-margin-left-medium | -6px | -
--td-avatar-group-margin-left-small | -4px | -
--td-avatar-bg-color | @brand-color-light-active | -
--td-avatar-border-color | #fff | -
--td-avatar-border-width-large | 8rpx | -
--td-avatar-border-width-medium | 6rpx | -
--td-avatar-border-width-small | 4rpx | -
--td-avatar-circle-border-radius | @radius-circle | -
--td-avatar-content-color | @brand-color | -
--td-avatar-icon-large-font-size | 64rpx | -
--td-avatar-icon-medium-font-size | 48rpx | -
--td-avatar-icon-small-font-size | 40rpx | -
--td-avatar-large-width | 128rpx | -
--td-avatar-margin-left | 0 | -
--td-avatar-medium-width | 96rpx | -
--td-avatar-round-border-radius | @radius-default | -
--td-avatar-small-width | 80rpx | -
--td-avatar-text-large-font-size | 16px | -
--td-avatar-text-medium-font-size | @font-size-base | -
--td-avatar-text-small-font-size | @font-size-s | -

View File

@ -0,0 +1,127 @@
---
title: Avatar 头像
description: 用于展示用户头像信息,除了纯展示也可点击进入个人详情等操作。
spline: data
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-99%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-85%25-blue" /></span>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-avatar": "tdesign-miniprogram/avatar/avatar",
"t-avatar-group": "tdesign-miniprogram/avatar-group/avatar-group"
}
```
## 代码演示
### 头像类型
图片头像
{{ image-avatar }}
字符头像
{{ character-avatar }}
图标头像
{{ icon-avatar }}
徽标头像
{{ badge-avatar }}
### 组合头像
纯展示
{{ exhibition }}
带操作
{{ action }}
### 头像尺寸
头像 large/medium/small 尺寸
{{ size }}
## API
### Avatar Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
alt | String | - | 头像替换文本,仅当图片加载失败时有效 | N
badge-props | Object | - | 头像右上角提示信息,继承 Badge 组件的全部特性。如小红点或者数字。TS 类型:`BadgeProps`[Badge API Documents](./badge?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar/type.ts) | N
bordered | Boolean | false | 已废弃。是否显示外边框 | N
hide-on-load-failed | Boolean | false | 加载失败时隐藏图片 | N
icon | String / Object | - | 图标。值为字符串表示图标名称,值为 `Object` 类型,表示透传至 `icon`。 | N
image | String | - | 图片地址 | N
image-props | Object | - | 透传至 Image 组件 | N
shape | String | circle | 形状。可选项circle/round。TS 类型:`ShapeEnum ` `type ShapeEnum = 'circle' \| 'round'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar/type.ts) | N
size | String | medium | 尺寸示例值small/medium/large/24px/38px 等 | N
### Avatar Events
名称 | 参数 | 描述
-- | -- | --
error | \- | 图片加载失败时触发
### Avatar 外部样式类
类名 | 说明
-- | --
t-class | 根节点样式类
t-class-image | 图片样式类
t-class-icon | 图标样式类
t-class-alt | 替代文本样式类
t-class-content | 内容样式类
### AvatarGroup Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
cascading | String | 'left-up' | 图片之间的层叠关系可选值左侧图片在上和右侧图片在上。可选项left-up/right-up。TS 类型:`CascadingValue` `type CascadingValue = 'left-up' \| 'right-up'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/avatar-group/type.ts) | N
collapse-avatar | String / Slot | - | 头像数量超出时,会出现一个头像折叠元素。该元素内容可自定义。默认为 `+N`。示例:`+5``...`, `更多` | N
max | Number | - | 能够同时显示的最多头像数量 | N
size | String | medium | 尺寸示例值small/medium/large/24px/38px 等。优先级低于 Avatar.size | N
### AvatarGroup 外部样式类
类名 | 说明
-- | --
t-class | 根节点样式类
t-class-image | 图片样式类
t-class-content | 内容样式类
### CSS 变量
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-avatar-group-margin-left-large | -8px | -
--td-avatar-group-margin-left-medium | -6px | -
--td-avatar-group-margin-left-small | -4px | -
--td-avatar-bg-color | @brand-color-light-active | -
--td-avatar-border-color | #fff | -
--td-avatar-border-width-large | 8rpx | -
--td-avatar-border-width-medium | 6rpx | -
--td-avatar-border-width-small | 4rpx | -
--td-avatar-circle-border-radius | @radius-circle | -
--td-avatar-content-color | @brand-color | -
--td-avatar-icon-large-font-size | 64rpx | -
--td-avatar-icon-medium-font-size | 48rpx | -
--td-avatar-icon-small-font-size | 40rpx | -
--td-avatar-large-width | 128rpx | -
--td-avatar-margin-left | 0 | -
--td-avatar-medium-width | 96rpx | -
--td-avatar-round-border-radius | @radius-default | -
--td-avatar-small-width | 80rpx | -
--td-avatar-text-large-font-size | 16px | -
--td-avatar-text-medium-font-size | @font-size-base | -
--td-avatar-text-small-font-size | @font-size-s | -

View File

@ -0,0 +1,23 @@
/// <reference types="miniprogram-api-typings" />
import { SuperComponent, RelationsOptions } from '../common/src/index';
export default class Avatar extends SuperComponent {
options: WechatMiniprogram.Component.ComponentOptions;
externalClasses: string[];
properties: import("./type").TdAvatarProps;
data: {
prefix: string;
classPrefix: string;
isShow: boolean;
zIndex: number;
borderedWithGroup: boolean;
};
relations: RelationsOptions;
observers: {
icon(icon: any): void;
};
methods: {
hide(): void;
updateCascading(zIndex: any): void;
onLoadError(e: WechatMiniprogram.CustomEvent): void;
};
}

View File

@ -0,0 +1,77 @@
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 { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import avatarProps from './props';
import { setIcon } from '../common/utils';
const { prefix } = config;
const name = `${prefix}-avatar`;
let Avatar = class Avatar extends SuperComponent {
constructor() {
super(...arguments);
this.options = {
multipleSlots: true,
styleIsolation: 'apply-shared',
};
this.externalClasses = [
`${prefix}-class`,
`${prefix}-class-image`,
`${prefix}-class-icon`,
`${prefix}-class-alt`,
`${prefix}-class-content`,
];
this.properties = avatarProps;
this.data = {
prefix,
classPrefix: name,
isShow: true,
zIndex: 0,
borderedWithGroup: false,
};
this.relations = {
'../avatar-group/avatar-group': {
type: 'ancestor',
linked(parent) {
var _a;
this.parent = parent;
this.setData({
size: (_a = this.data.size) !== null && _a !== void 0 ? _a : parent.data.size,
borderedWithGroup: true,
});
},
},
};
this.observers = {
icon(icon) {
const obj = setIcon('icon', icon, '');
this.setData(Object.assign({}, obj));
},
};
this.methods = {
hide() {
this.setData({
isShow: false,
});
},
updateCascading(zIndex) {
this.setData({ zIndex });
},
onLoadError(e) {
if (this.properties.hideOnLoadFailed) {
this.setData({
isShow: false,
});
}
this.triggerEvent('error', e.detail);
},
};
}
};
Avatar = __decorate([
wxComponent()
], Avatar);
export default Avatar;

View File

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {
"t-icon": "../icon/icon",
"t-badge": "../badge/badge",
"t-image": "../image/image"
}
}

View File

@ -0,0 +1,54 @@
<import src="../common/template/icon.wxml" />
<wxs src="../common/utils.wxs" module="_" />
<wxs src="./avatar.wxs" module="this" />
<view
class="{{classPrefix}}__wrapper class {{prefix}}-class"
style="{{_._style([this.getStyles(isShow, zIndex), style, customStyle])}}"
>
<t-badge
color="{{badgeProps.color || ''}}"
content="{{badgeProps.content || ''}}"
count="{{badgeProps.count || 0}}"
dot="{{badgeProps.dot || false}}"
max-count="{{badgeProps.maxCount || 99}}"
offset="{{badgeProps.offset || []}}"
shape="{{badgeProps.shape || 'circle'}}"
show-zero="{{badgeProps.showZero || false}}"
size="{{badgeProps.size || 'medium'}}"
t-class="{{badgeProps.tClass}}"
t-class-content="{{badgeProps.tClassContent}}"
t-class-count="{{badgeProps.tClassCount}}"
>
<view
class="{{this.getClass(classPrefix, size, shape, bordered || borderedWithGroup)}} {{prefix}}-class-image"
style="{{this.getSize(size)}}"
aria-label="{{ ariaLabel || alt ||'头像'}}"
aria-role="{{ ariaRole || 'img'}}"
aria-hidden="{{ ariaHidden }}"
>
<t-image
wx:if="{{image}}"
t-class="{{prefix}}-image {{classPrefix}}__image"
t-class-load="{{prefix}}-class-alt"
style="{{imageProps && imageProps.style || ''}}"
src="{{image}}"
mode="{{imageProps && imageProps.mode || 'aspectFill'}}"
lazy="{{imageProps && imageProps.lazy || false}}"
loading="{{imageProps && imageProps.loading || 'default'}}"
shape="{{imageProps && imageProps.shape || 'round'}}"
webp="{{imageProps && imageProps.webp || false}}"
error="{{alt || 'default'}}"
bind:error="onLoadError"
/>
<template
wx:elif="{{iconName || _.isNoEmptyObj(iconData)}}"
is="icon"
data="{{class: classPrefix + '__icon', tClass: prefix + '-class-icon', name: iconName, ...iconData}}"
/>
<view wx:else class="{{classPrefix}}__text {{prefix}}-class-content">
<slot />
</view>
</view>
</t-badge>
</view>

View File

@ -0,0 +1,26 @@
module.exports = {
getClass: function (classPrefix, size, shape, bordered) {
var hasPx = (size || '').indexOf('px') > -1;
var borderSize = hasPx ? 'medium' : size;
var classNames = [
classPrefix,
classPrefix + (shape === 'round' ? '--round' : '--circle'),
bordered ? classPrefix + '--border' + ' ' + classPrefix + '--border-' + borderSize : '',
hasPx ? '' : classPrefix + '--' + size,
];
return classNames.join(' ');
},
getSize: function (size = 'medium') {
var pxIndex = size.indexOf('px');
if (pxIndex > -1) {
return 'width:' + size + ';height:' + size + ';font-size:' + ((size.slice(0, pxIndex) / 8) * 3 + 2) + 'px;';
}
},
getStyles: function (isShow, zIndex) {
var displayStyle = isShow ? '' : 'display: none;';
var zIndexStyle = zIndex ? 'z-index:' + zIndex + ';' : '';
return displayStyle + zIndexStyle;
},
};

View File

@ -0,0 +1,104 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-avatar {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
background-color: var(--td-avatar-bg-color, var(--td-brand-color-light-active, var(--td-primary-color-2, #d9e1ff)));
color: var(--td-avatar-content-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-avatar__wrapper {
display: inline-flex;
position: relative;
vertical-align: top;
margin-left: var(--td-avatar-margin-left, 0);
}
.t-avatar--large {
width: var(--td-avatar-large-width, 128rpx);
height: var(--td-avatar-large-width, 128rpx);
font-size: var(--td-avatar-text-large-font-size, 16px);
}
.t-avatar--large .t-avatar__icon {
font-size: var(--td-avatar-icon-large-font-size, 64rpx);
}
.t-avatar--medium {
width: var(--td-avatar-medium-width, 96rpx);
height: var(--td-avatar-medium-width, 96rpx);
font-size: var(--td-avatar-text-medium-font-size, var(--td-font-size-base, 28rpx));
}
.t-avatar--medium .t-avatar__icon {
font-size: var(--td-avatar-icon-medium-font-size, 48rpx);
}
.t-avatar--small {
width: var(--td-avatar-small-width, 80rpx);
height: var(--td-avatar-small-width, 80rpx);
font-size: var(--td-avatar-text-small-font-size, var(--td-font-size-s, 24rpx));
}
.t-avatar--small .t-avatar__icon {
font-size: var(--td-avatar-icon-small-font-size, 40rpx);
}
.t-avatar .t-image,
.t-avatar__image {
width: 100%;
height: 100%;
}
.t-avatar--circle {
border-radius: var(--td-avatar-circle-border-radius, var(--td-radius-circle, 50%));
overflow: hidden;
}
.t-avatar--round {
border-radius: var(--td-avatar-round-border-radius, var(--td-radius-default, 12rpx));
overflow: hidden;
}
.t-avatar__text,
.t-avatar__icon {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.t-avatar__text:empty,
.t-avatar__icon:empty {
width: 0;
height: 0;
}
.t-avatar--border {
border-color: var(--td-avatar-border-color, #fff);
border-style: solid;
}
.t-avatar--border-small {
border-width: var(--td-avatar-border-width-small, 4rpx);
}
.t-avatar--border-medium {
border-width: var(--td-avatar-border-width-medium, 6rpx);
}
.t-avatar--border-large {
border-width: var(--td-avatar-border-width-large, 8rpx);
}

View File

@ -0,0 +1,3 @@
import { TdAvatarProps } from './type';
declare const props: TdAvatarProps;
export default props;

View File

@ -0,0 +1,39 @@
const props = {
alt: {
type: String,
value: '',
},
badgeProps: {
type: Object,
},
bordered: {
type: Boolean,
value: false,
},
externalClasses: {
type: Array,
},
hideOnLoadFailed: {
type: Boolean,
value: false,
},
icon: {
type: null,
},
image: {
type: String,
value: '',
},
imageProps: {
type: Object,
},
shape: {
type: String,
value: 'circle',
},
size: {
type: String,
value: 'medium',
},
};
export default props;

View File

@ -0,0 +1,48 @@
import { BadgeProps } from '../badge/index';
export interface TdAvatarProps {
alt?: {
type: StringConstructor;
value?: string;
};
badgeProps?: {
type: ObjectConstructor;
value?: BadgeProps;
};
bordered?: {
type: BooleanConstructor;
value?: boolean;
};
style?: {
type: StringConstructor;
value?: string;
};
externalClasses?: {
type: ArrayConstructor;
value?: ['t-class', 't-class-image', 't-class-icon', 't-class-alt', 't-class-content'];
};
hideOnLoadFailed?: {
type: BooleanConstructor;
value?: boolean;
};
icon?: {
type: null;
value?: string | object;
};
image?: {
type: StringConstructor;
value?: string;
};
imageProps?: {
type: ObjectConstructor;
value?: object;
};
shape?: {
type: StringConstructor;
value?: ShapeEnum;
};
size?: {
type: StringConstructor;
value?: string;
};
}
export declare type ShapeEnum = 'circle' | 'round';

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,31 @@
:: BASE_DOC ::
## API
### BackTop Props
name | type | default | description | required
-- | -- | -- | -- | --
external-classes | Array | - | `['t-class', 't-class-icon', 't-class-text']` | N
fixed | Boolean | true | \- | N
icon | String / Boolean / Object / Slot | - | \- | N
text | String | '' | \- | N
theme | String | round | optionsround/half-round/round-dark/half-round-dark | N
### BackTop Events
name | params | description
-- | -- | --
to-top | \- | \-
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-back-top-round-bg-color | @font-white-1 | -
--td-back-top-round-border-color | @component-border | -
--td-back-top-round-border-radius | @radius-circle | -
--td-back-top-round-color | @font-gray-1 | -
--td-back-top-round-dark-bg-color | @gray-color-14 | -
--td-back-top-round-dark-color | @font-white-1 | -

View File

@ -0,0 +1,59 @@
---
title: BackTop 返回顶部
description: 用于当页面过长往下滑动时,帮助用户快速回到页面顶部。
spline: navigation
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-100%25-blue" /></span>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-back-top": "tdesign-miniprogram/back-top/back-top",
}
```
## 代码演示
<img src="https://tdesign.gtimg.com/miniprogram/readme/backtop-1.png" width="375px" height="50%">
### 基础返回顶部
{{ base }}
## API
### BackTop Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
fixed | Boolean | true | 是否绝对定位固定到屏幕右下方 | N
icon | String / Boolean / Object / Slot | true | 图标。值为 `false` 表示不显示图标。不传表示使用默认图标 `'backtop'` | N
text | String | '' | 文案 | N
theme | String | round | 预设的样式类型。可选项round/half-round/round-dark/half-round-dark | N
### BackTop Events
名称 | 参数 | 描述
-- | -- | --
to-top | \- | 点击触发
### BackTop 外部样式类
类名 | 说明
-- | --
t-class | 根节点样式类
t-class-icon | 图标样式类
t-class-text | 文本样式类
### CSS 变量
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-back-top-round-bg-color | @font-white-1 | -
--td-back-top-round-border-color | @component-border | -
--td-back-top-round-border-radius | @radius-circle | -
--td-back-top-round-color | @font-gray-1 | -
--td-back-top-round-dark-bg-color | @gray-color-14 | -
--td-back-top-round-dark-color | @font-white-1 | -

View File

@ -0,0 +1,24 @@
import { SuperComponent, RelationsOptions } from '../common/src/index';
export default class BackTop extends SuperComponent {
externalClasses: string[];
options: {
multipleSlots: boolean;
};
properties: import("./type").TdBackTopProps;
relations: RelationsOptions;
data: {
prefix: string;
classPrefix: string;
_icon: any;
};
observers: {
icon(): void;
};
lifetimes: {
ready(): void;
};
methods: {
setIcon(v: any): void;
toTop(): void;
};
}

View File

@ -0,0 +1,67 @@
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 { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import props from './props';
import { calcIcon } from '../common/utils';
const { prefix } = config;
const name = `${prefix}-back-top`;
let BackTop = class BackTop extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`, `${prefix}-class-icon`, `${prefix}-class-text`];
this.options = {
multipleSlots: true,
};
this.properties = props;
this.relations = {
'../pull-down-refresh/pull-down-refresh': {
type: 'ancestor',
},
};
this.data = {
prefix,
classPrefix: name,
_icon: null,
};
this.observers = {
icon() {
this.setIcon();
},
};
this.lifetimes = {
ready() {
const { icon } = this.properties;
this.setIcon(icon);
},
};
this.methods = {
setIcon(v) {
this.setData({
_icon: calcIcon(v, 'backtop'),
});
},
toTop() {
var _a;
this.triggerEvent('to-top');
if (this.$parent) {
(_a = this.$parent) === null || _a === void 0 ? void 0 : _a.setScrollTop(0);
}
else {
wx.pageScrollTo({
scrollTop: 0,
duration: 300,
});
}
},
};
}
};
BackTop = __decorate([
wxComponent()
], BackTop);
export default BackTop;

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"t-icon": "../icon/icon"
}
}

View File

@ -0,0 +1,16 @@
<import src="../common/template/icon.wxml" />
<wxs src="../common/utils.wxs" module="_" />
<view
style="{{_._style([style, customStyle])}}"
class="class {{prefix}}-class {{_.cls(classPrefix, [['fixed', fixed], theme])}}"
bindtap="toTop"
aria-role="button"
>
<view class="{{classPrefix}}__icon" aria-hidden>
<slot name="icon" />
<template wx:if="{{_icon}}" is="icon" data="{{tClass: prefix + '-class-icon', ..._icon }}" />
</view>
<view wx:if="{{!!text}}" class="{{classPrefix}}__text--{{theme}} {{prefix}}-class-text">{{text}}</view>
<slot />
</view>

View File

@ -0,0 +1,89 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-back-top {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: transparent;
overflow: hidden;
box-sizing: border-box;
transition: height 0.2s;
height: auto;
}
.t-back-top--fixed {
position: fixed;
right: var(--td-spacer, 16rpx);
bottom: var(--td-spacer-2, 32rpx);
}
.t-back-top--round,
.t-back-top--round-dark {
width: 96rpx;
height: 96rpx;
border-radius: var(--td-back-top-round-border-radius, var(--td-radius-circle, 50%));
}
.t-back-top--round,
.t-back-top--half-round {
color: var(--td-back-top-round-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
border: 1rpx solid var(--td-back-top-round-border-color, var(--td-component-border, var(--td-gray-color-4, #dcdcdc)));
background-color: var(--td-back-top-round-bg-color, var(--td-font-white-1, #ffffff));
}
.t-back-top--round-dark,
.t-back-top--half-round-dark {
color: var(--td-back-top-round-dark-color, var(--td-font-white-1, #ffffff));
background-color: var(--td-back-top-round-dark-bg-color, var(--td-gray-color-14, #181818));
}
.t-back-top--half-round,
.t-back-top--half-round-dark {
width: 120rpx;
height: 80rpx;
border-radius: var(--td-back-top-half-round-border-radius, var(--td-radius-round, 999px)) 0 0 var(--td-back-top-half-round-border-radius, var(--td-radius-round, 999px));
flex-direction: row;
right: 0;
}
.t-back-top__text--round,
.t-back-top__text--round-dark,
.t-back-top__text--half-round,
.t-back-top__text--half-round-dark {
font-size: var(--td-font-size, 20rpx);
line-height: 24rpx;
}
.t-back-top__text--half-round,
.t-back-top__text--half-round-dark {
width: 2em;
}
.t-back-top__icon:not(:empty) + .t-back-top__text--half-round,
.t-back-top__icon:not(:empty) + .t-back-top__text--half-round-dark {
margin-left: 8rpx;
}
.t-back-top__icon {
display: flex;
justify-content: center;
align-items: center;
font-size: 44rpx;
}

View File

@ -0,0 +1,3 @@
import { TdBackTopProps } from './type';
declare const props: TdBackTopProps;
export default props;

View File

@ -0,0 +1,22 @@
const props = {
externalClasses: {
type: Array,
},
fixed: {
type: Boolean,
value: true,
},
icon: {
type: null,
value: true,
},
text: {
type: String,
value: '',
},
theme: {
type: String,
value: 'round',
},
};
export default props;

View File

@ -0,0 +1,26 @@
export interface TdBackTopProps {
style?: {
type: StringConstructor;
value?: string;
};
externalClasses?: {
type: ArrayConstructor;
value?: ['t-class', 't-class-icon', 't-class-text'];
};
fixed?: {
type: BooleanConstructor;
value?: boolean;
};
icon?: {
type: null;
value?: boolean | string | object;
};
text?: {
type: StringConstructor;
value?: string;
};
theme?: {
type: StringConstructor;
value?: 'round' | 'half-round' | 'round-dark' | 'half-round-dark';
};
}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,36 @@
:: BASE_DOC ::
## API
### Badge Props
name | type | default | description | required
-- | -- | -- | -- | --
color | String | - | \- | N
content | String | - | \- | N
count | String / Number / Slot | 0 | [see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/src/common/common.ts) | N
dot | Boolean | false | \- | N
external-classes | Array | - | `['t-class', 't-class-content', 't-class-count']` | N
max-count | Number | 99 | \- | N
offset | Array | - | Typescript`Array<string \| number>` | N
shape | String | circle | optionscircle/square/bubble/ribbon | N
show-zero | Boolean | false | \- | N
size | String | medium | optionsmedium/large | N
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-badge-basic-height | 32rpx | -
--td-badge-basic-padding | 8rpx | -
--td-badge-basic-width | 32rpx | -
--td-badge-bg-color | @error-color | -
--td-badge-border-radius | 4rpx | -
--td-badge-bubble-border-radius | 20rpx 20rpx 20rpx 1px | -
--td-badge-dot-size | 16rpx | -
--td-badge-font-size | @font-size-xs | -
--td-badge-font-weight | 600 | -
--td-badge-large-font-size | @font-size-s | -
--td-badge-large-height | 40rpx | -
--td-badge-large-padding | 10rpx | -
--td-badge-text-color | @font-white-1 | -

View File

@ -0,0 +1,71 @@
---
title: Badge 徽标
description: 用于告知用户,该区域的状态变化或者待处理任务的数量。
spline: data
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-100%25-blue" /></span>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-badge": "tdesign-miniprogram/badge/badge"
}
```
## 代码演示
### 组件类型
{{ base }}
### 组件样式
{{ theme }}
### 组件尺寸
{{ size }}
## API
### Badge Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
color | String | - | 颜色 | N
content | String | - | 徽标内容,示例:`content='自定义内容'`。也可以使用默认插槽定义 | N
count | String / Number / Slot | 0 | 徽标右上角内容。可以是数字,也可以是文字。如:'new'/3/99+。特殊:值为空表示使用插槽渲染。[通用类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/src/common/common.ts) | N
dot | Boolean | false | 是否为红点 | N
max-count | Number | 99 | 封顶的数字值 | N
offset | Array | - | 设置状态点的位置偏移,示例:[-10, 20] 或 ['10em', '8rem']。TS 类型:`Array<string \| number>` | N
shape | String | circle | 形状。可选项circle/square/bubble/ribbon | N
show-zero | Boolean | false | 当数值为 0 时,是否展示徽标 | N
size | String | medium | 尺寸。可选项medium/large | N
### Badge 外部样式类
类名 | 说明
-- | --
t-class | 根节点样式类
t-class-count | 计数样式类
t-class-content | 内容样式类
### CSS 变量
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-badge-basic-height | 32rpx | -
--td-badge-basic-padding | 8rpx | -
--td-badge-basic-width | 32rpx | -
--td-badge-bg-color | @error-color | -
--td-badge-border-radius | 4rpx | -
--td-badge-bubble-border-radius | 20rpx 20rpx 20rpx 1px | -
--td-badge-dot-size | 16rpx | -
--td-badge-font-size | @font-size-xs | -
--td-badge-font-weight | 600 | -
--td-badge-large-font-size | @font-size-s | -
--td-badge-large-height | 40rpx | -
--td-badge-large-padding | 10rpx | -
--td-badge-text-color | @font-white-1 | -

View File

@ -0,0 +1,21 @@
import { SuperComponent } from '../common/src/index';
import type { TdBadgeProps } from './type';
export interface BadgeProps extends TdBadgeProps {
}
export default class Badge extends SuperComponent {
options: {
multipleSlots: boolean;
};
externalClasses: string[];
properties: TdBadgeProps;
data: {
prefix: string;
classPrefix: string;
value: string;
labelID: string;
descriptionID: string;
};
lifetimes: {
ready(): void;
};
}

View File

@ -0,0 +1,43 @@
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 { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import props from './props';
import { uniqueFactory } from '../common/utils';
const { prefix } = config;
const name = `${prefix}-badge`;
const getUniqueID = uniqueFactory('badge');
let Badge = class Badge extends SuperComponent {
constructor() {
super(...arguments);
this.options = {
multipleSlots: true,
};
this.externalClasses = [`${prefix}-class`, `${prefix}-class-count`, `${prefix}-class-content`];
this.properties = props;
this.data = {
prefix,
classPrefix: name,
value: '',
labelID: '',
descriptionID: '',
};
this.lifetimes = {
ready() {
const uniqueID = getUniqueID();
this.setData({
labelID: `${uniqueID}_label`,
descriptionID: `${uniqueID}_description`,
});
},
};
}
};
Badge = __decorate([
wxComponent()
], Badge);
export default Badge;

View File

@ -0,0 +1,5 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -0,0 +1,44 @@
<wxs src="./badge.wxs" module="this" />
<wxs src="../common/utils.wxs" module="_" />
<!--
1. labelID 用于描述当前元素的文本
2. descriptionID 用于描述badge消息的文本
3. role=option一般用于多个内容合并焦点连续朗读
-->
<view
style="{{_._style([style, customStyle])}}"
class="{{this.getBadgeOuterClass({shape})}} class {{prefix}}-class"
aria-labelledby="{{labelID}}"
aria-describedby="{{descriptionID}}"
aria-role="{{ ariaRole || 'option'}}"
>
<view id="{{labelID}}" class="{{classPrefix}}__content {{prefix}}-class-content" aria-hidden="true">
<slot wx:if="{{!content}}" class="{{classPrefix}}__content-slot" />
<text wx:else class="{{classPrefix}}__content-text">{{content}}</text>
</view>
<view
aria-hidden="true"
aria-label="{{ ariaLabel || _.getBadgeAriaLabel({dot, count, maxCount}) }}"
wx:if="{{this.isShowBadge({dot,count,showZero})}}"
id="{{descriptionID}}"
class="{{this.getBadgeInnerClass({dot, size, shape, count})}} {{prefix}}-has-count {{prefix}}-class-count"
style="{{this.getBadgeStyles({color, offset})}}"
aria-hidden="true"
aria-label="{{ ariaLabel || _.getBadgeAriaLabel({dot, count, maxCount}) }}"
>
<view
wx:if="{{shape == 'ribbon'}}"
class="t-badge__ribbon--before"
style="{{color ? 'border-color: ' + color : ''}}"
/>
{{ this.getBadgeValue({dot, count, maxCount}) }}
<view
wx:if="{{shape == 'ribbon'}}"
class="t-badge__ribbon--after"
style="{{color ? 'border-color: ' + color : ''}}"
/>
</view>
<slot name="count" />
</view>

View File

@ -0,0 +1,70 @@
var getBadgeValue = function (props) {
if (props.dot) {
return '';
}
if (isNaN(props.count) || isNaN(props.maxCount)) {
return props.count;
}
return parseInt(props.count) > props.maxCount ? props.maxCount + '+' : props.count;
};
var hasUnit = function (unit) {
return (
unit.indexOf('px') > 0 ||
unit.indexOf('rpx') > 0 ||
unit.indexOf('em') > 0 ||
unit.indexOf('rem') > 0 ||
unit.indexOf('%') > 0 ||
unit.indexOf('vh') > 0 ||
unit.indexOf('vm') > 0
);
};
var getBadgeStyles = function (props) {
var styleStr = '';
if (props.color) {
styleStr += 'background:' + props.color + ';';
}
if (props.offset[0]) {
styleStr += 'right:' + (hasUnit(props.offset[0].toString()) ? props.offset[0] : props.offset[0] + 'px') + ';';
}
if (props.offset[1]) {
styleStr += 'top:' + (hasUnit(props.offset[1].toString()) ? props.offset[1] : props.offset[1] + 'px') + ';';
}
return styleStr;
};
var getBadgeOuterClass = function (props) {
var baseClass = 't-badge';
var classNames = [baseClass, props.shape === 'ribbon' ? baseClass + '__ribbon-outer' : ''];
return classNames.join(' ');
};
var getBadgeInnerClass = function (props) {
var baseClass = 't-badge';
var classNames = [
baseClass + '--basic',
props.dot ? baseClass + '--dot' : '',
baseClass + '--' + props.size,
baseClass + '--' + props.shape,
!props.dot && props.count ? baseClass + '--count' : '',
];
return classNames.join(' ');
};
var isShowBadge = function (props) {
if (props.dot) {
return true;
}
if (!props.showZero && !isNaN(props.count) && parseInt(props.count) === 0) {
return false;
}
if (props.count == null) return false;
return true;
};
module.exports.getBadgeValue = getBadgeValue;
module.exports.getBadgeStyles = getBadgeStyles;
module.exports.getBadgeOuterClass = getBadgeOuterClass;
module.exports.getBadgeInnerClass = getBadgeInnerClass;
module.exports.isShowBadge = isShowBadge;

View File

@ -0,0 +1,108 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-badge {
position: relative;
display: inline-block;
vertical-align: top;
}
.t-badge--basic {
z-index: 100;
padding: 0 var(--td-badge-basic-padding, 8rpx);
font-size: var(--td-badge-font-size, var(--td-font-size-xs, var(--td-font-size, 20rpx)));
color: var(--td-badge-text-color, var(--td-font-white-1, #ffffff));
background-color: var(--td-badge-bg-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
text-align: center;
height: var(--td-badge-basic-height, 32rpx);
line-height: var(--td-badge-basic-height, 32rpx);
font-weight: var(--td-badge-font-weight, 600);
border-radius: var(--td-badge-border-radius, 4rpx);
}
.t-badge--dot {
height: var(--td-badge-dot-size, 16rpx);
border-radius: 50%;
min-width: var(--td-badge-dot-size, 16rpx);
padding: 0;
}
.t-badge--count {
min-width: var(--td-badge-basic-width, 32rpx);
white-space: nowrap;
box-sizing: border-box;
}
.t-badge--circle {
border-radius: calc(var(--td-badge-basic-height, 32rpx) / 2);
}
.t-badge__ribbon-outer {
position: absolute;
top: 0;
right: 0;
}
.t-badge__ribbon--before,
.t-badge__ribbon--after {
content: '';
position: absolute;
width: 0;
height: 0;
bottom: 0;
border-bottom: var(--td-badge-basic-height, 32rpx) solid var(--td-badge-bg-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
}
.t-badge__ribbon--before {
left: calc(-1 * var(--td-badge-basic-height, 32rpx) + 1rpx);
border-left: var(--td-badge-basic-height, 32rpx) solid transparent;
}
.t-badge__ribbon--after {
right: calc(-1 * var(--td-badge-basic-height, 32rpx) + 1rpx);
border-right: var(--td-badge-basic-height, 32rpx) solid transparent;
}
.t-badge--ribbon {
display: inline-block;
transform: rotate(45deg);
border-radius: 0;
}
.t-badge--bubble {
border-radius: var(--td-badge-bubble-border-radius, 20rpx 20rpx 20rpx 1px);
}
.t-badge--large {
font-size: var(--td-badge-large-font-size, var(--td-font-size-s, 24rpx));
height: var(--td-badge-large-height, 40rpx);
min-width: var(--td-badge-large-height, 40rpx);
line-height: var(--td-badge-large-height, 40rpx);
padding: 0 var(--td-badge-large-padding, 10rpx);
}
.t-badge--large.t-badge--circle {
border-radius: calc(var(--td-badge-large-height, 40rpx) / 2);
}
.t-badge__content:not(:empty) + .t-has-count {
transform: translate(50%, -50%);
position: absolute;
right: 0;
top: 0;
}
.t-badge__content-text {
display: block;
line-height: 48rpx;
}

View File

@ -0,0 +1,3 @@
export * from './type';
export * from './props';
export * from './badge';

View File

@ -0,0 +1,3 @@
export * from './type';
export * from './props';
export * from './badge';

View File

@ -0,0 +1,3 @@
import { TdBadgeProps } from './type';
declare const props: TdBadgeProps;
export default props;

View File

@ -0,0 +1,41 @@
const props = {
color: {
type: String,
value: '',
},
content: {
type: String,
value: '',
},
count: {
type: null,
value: 0,
},
dot: {
type: Boolean,
value: false,
},
externalClasses: {
type: Array,
},
maxCount: {
type: Number,
value: 99,
},
offset: {
type: Array,
},
shape: {
type: String,
value: 'circle',
},
showZero: {
type: Boolean,
value: false,
},
size: {
type: String,
value: 'medium',
},
};
export default props;

View File

@ -0,0 +1,42 @@
export interface TdBadgeProps {
color?: {
type: StringConstructor;
value?: string;
};
content?: {
type: StringConstructor;
value?: string;
};
count?: {
type: null;
value?: string | number;
};
dot?: {
type: BooleanConstructor;
value?: boolean;
};
externalClasses?: {
type: ArrayConstructor;
value?: ['t-class', 't-class-content', 't-class-count'];
};
maxCount?: {
type: NumberConstructor;
value?: number;
};
offset?: {
type: ArrayConstructor;
value?: Array<string | number>;
};
shape?: {
type: StringConstructor;
value?: 'circle' | 'square' | 'bubble' | 'ribbon';
};
showZero?: {
type: BooleanConstructor;
value?: boolean;
};
size?: {
type: StringConstructor;
value?: 'medium' | 'large';
};
}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,148 @@
:: BASE_DOC ::
## API
### Button Props
name | type | default | description | required
-- | -- | -- | -- | --
block | Boolean | false | make button to be a block-level element | N
content | String / Slot | - | button's children elements | N
custom-dataset | Object | - | Typescript`any` | N
disabled | Boolean | false | disable the button, make it can not be clicked | N
external-classes | Array | - | `['t-class', 't-class-icon', 't-class-loading']` | N
ghost | Boolean | false | make background-color to be transparent | N
icon | String / Object | - | icon name | N
loading | Boolean | false | set button to be loading state | N
loading-props | Object | - | Typescript`LoadingProps`[Loading API Documents](./loading?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/button/type.ts) | N
shape | String | rectangle | button shape。optionsrectangle/square/round/circle | N
size | String | medium | a button has three size。optionssmall/medium/large。Typescript`SizeEnum` | N
suffix | Slot | - | \- | N
theme | String | default | button theme。optionsdefault/primary/danger | N
type | String | - | type of button element, same as formType of Miniprogram。optionssubmit/reset | N
variant | String | base | button variant。optionsbase/outline/text | N
open-type | String | - | optionscontact/share/getPhoneNumber/getUserInfo/launchApp/openSetting/feedback/chooseAvatar | N
hover-stop-propagation | Boolean | false | \- | N
hover-start-time | Number | 20 | \- | N
hover-stay-time | Number | 70 | \- | N
lang | String | en | optionsen/zh_CN/zh_TW | N
session-from | String | - | \- | N
send-message-title | String | 当前标题 | \- | N
send-message-path | String | 当前分享路径 | \- | N
send-message-img | String | 截图 | \- | N
app-parameter | String | - | \- | N
show-message-card | Boolean | false | \- | N
bindgetuserinfo | Eventhandle | - | \- | N
bindcontact | Eventhandle | - | \- | N
bindgetphonenumber | Eventhandle | - | \- | N
binderror | Eventhandle | - | \- | N
bindopensetting | Eventhandle | - | \- | N
bindlaunchapp | Eventhandle | - | \- | N
bindchooseavatar | Eventhandle | - | \- | N
### Button Events
name | params | description
-- | -- | --
tap | `(e: MouseEvent)` | trigger on click
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-button-border-radius | @radius-default | -
--td-button-border-width | 4rpx | -
--td-button-danger-active-bg-color | @error-color-7 | -
--td-button-danger-active-border-color | @error-color-7 | -
--td-button-danger-bg-color | @error-color | -
--td-button-danger-border-color | @error-color | -
--td-button-danger-color | @font-white-1 | -
--td-button-danger-dashed-border-color | @button-danger-dashed-color | -
--td-button-danger-dashed-color | @error-color | -
--td-button-danger-dashed-disabled-color | @button-danger-disabled-color | -
--td-button-danger-disabled-bg | @error-color-3 | -
--td-button-danger-disabled-border-color | @error-color-3 | -
--td-button-danger-disabled-color | @font-white-1 | -
--td-button-danger-outline-active-bg-color | @bg-color-container-active | -
--td-button-danger-outline-active-border-color | @error-color-7 | -
--td-button-danger-outline-border-color | @button-danger-outline-color | -
--td-button-danger-outline-color | @error-color | -
--td-button-danger-outline-disabled-color | @error-color-3 | -
--td-button-danger-text-active-bg-color | @bg-color-container-active | -
--td-button-danger-text-color | @error-color | -
--td-button-danger-text-disabled-color | @button-danger-disabled-color | -
--td-button-default-active-bg-color | @bg-color-component-active | -
--td-button-default-active-border-color | @bg-color-component-active | -
--td-button-default-bg-color | @bg-color-component | -
--td-button-default-border-color | @bg-color-component | -
--td-button-default-color | @font-gray-1 | -
--td-button-default-disabled-bg | @bg-color-component-disabled | -
--td-button-default-disabled-border-color | @bg-color-component-disabled | -
--td-button-default-disabled-color | @font-gray-4 | -
--td-button-default-outline-active-bg-color | @bg-color-container-active | -
--td-button-default-outline-active-border-color | @component-border | -
--td-button-default-outline-border-color | @component-border | -
--td-button-default-outline-color | @font-gray-1 | -
--td-button-default-outline-disabled-color | @component-border | -
--td-button-default-text-active-bg-color | @bg-color-container-active | -
--td-button-extra-small-font-size | @font-size-base | -
--td-button-extra-small-height | 56rpx | -
--td-button-extra-small-icon-font-size | 36rpx | -
--td-button-extra-small-padding-horizontal | 16rpx | -
--td-button-font-weight | 600 | -
--td-button-ghost-border-color | @button-ghost-color | -
--td-button-ghost-color | @bg-color-container | -
--td-button-ghost-danger-border-color | @error-color | -
--td-button-ghost-danger-color | @error-color | -
--td-button-ghost-disabled-color | rgba(255, 255, 255, 0.35) | -
--td-button-ghost-primary-border-color | @brand-color | -
--td-button-ghost-primary-color | @brand-color | -
--td-button-icon-border-radius | 8rpx | -
--td-button-icon-spacer | @spacer | -
--td-button-large-font-size | @font-size-m | -
--td-button-large-height | 96rpx | -
--td-button-large-icon-font-size | 48rpx | -
--td-button-large-padding-horizontal | 40rpx | -
--td-button-light-active-bg-color | @brand-color-light-active | -
--td-button-light-active-border-color | @brand-color-light-active | -
--td-button-light-bg-color | @brand-color-light | -
--td-button-light-border-color | @brand-color-light | -
--td-button-light-color | @brand-color | -
--td-button-light-disabled-bg | @brand-color-light | -
--td-button-light-disabled-border-color | @brand-color-light | -
--td-button-light-disabled-color | @brand-color-disabled | -
--td-button-light-outline-active-bg-color | @brand-color-light-active | -
--td-button-light-outline-active-border-color | @brand-color-active | -
--td-button-light-outline-bg-color | @brand-color-light | -
--td-button-light-outline-border-color | @button-light-outline-color | -
--td-button-light-outline-color | @brand-color | -
--td-button-light-outline-disabled-color | @brand-color-disabled | -
--td-button-light-text-active-bg-color | @bg-color-container-active | -
--td-button-light-text-color | @brand-color | -
--td-button-medium-font-size | @font-size-m | -
--td-button-medium-height | 80rpx | -
--td-button-medium-icon-font-size | 40rpx | -
--td-button-medium-padding-horizontal | 32rpx | -
--td-button-primary-active-bg-color | @brand-color-active | -
--td-button-primary-active-border-color | @brand-color-active | -
--td-button-primary-bg-color | @brand-color | -
--td-button-primary-border-color | @brand-color | -
--td-button-primary-color | @font-white-1 | -
--td-button-primary-dashed-border-color | @button-primary-dashed-color | -
--td-button-primary-dashed-color | @brand-color | -
--td-button-primary-dashed-disabled-color | @brand-color-disabled | -
--td-button-primary-disabled-bg | @brand-color-disabled | -
--td-button-primary-disabled-border-color | @brand-color-disabled | -
--td-button-primary-disabled-color | @font-white-1 | -
--td-button-primary-outline-active-bg-color | @bg-color-container-active | -
--td-button-primary-outline-active-border-color | @brand-color-active | -
--td-button-primary-outline-border-color | @button-primary-outline-color | -
--td-button-primary-outline-color | @brand-color | -
--td-button-primary-outline-disabled-color | @brand-color-disabled | -
--td-button-primary-text-active-bg-color | @bg-color-container-active | -
--td-button-primary-text-color | @brand-color | -
--td-button-primary-text-disabled-color | @brand-color-disabled | -
--td-button-small-font-size | @font-size-base | -
--td-button-small-height | 64rpx | -
--td-button-small-icon-font-size | 36rpx | -
--td-button-small-padding-horizontal | 24rpx | -

View File

@ -0,0 +1,214 @@
---
title: Button 按钮
description: 用于开启一个闭环的操作任务,如“删除”对象、“购买”商品等。
spline: base
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-83%25-blue" /></span>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-button": "tdesign-miniprogram/button/button"
}
```
## 代码演示
### 01 组件类型
基础按钮
{{ base }}
图标按钮
{{ icon-btn }}
幽灵按钮
{{ ghost-btn }}
组合按钮
{{ group-btn }}
通栏按钮
{{ block-btn }}
### 02 组件状态
按钮禁用态
{{ disabled }}
### 03 组件样式
按钮尺寸
{{ size }}
按钮形状
{{ shape }}
按钮主题
{{ theme }}
## API
### Button Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
block | Boolean | false | 是否为块级元素 | N
content | String / Slot | - | 按钮内容 | N
custom-dataset | Object | - | 自定义 dataset可通过 event.currentTarget.dataset.custom 获取。TS 类型:`any` | N
disabled | Boolean | false | 禁用状态 | N
ghost | Boolean | false | 是否为幽灵按钮(镂空按钮) | N
icon | String / Object | - | 图标名称。值为字符串表示图标名称,值为 `Object` 类型,表示透传至 `icon`。 | N
loading | Boolean | false | 是否显示为加载状态 | N
loading-props | Object | - | 透传至 Loading 组件。TS 类型:`LoadingProps`[Loading API Documents](./loading?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/button/type.ts) | N
shape | String | rectangle | 按钮形状,有 4 种长方形、正方形、圆角长方形、圆形。可选项rectangle/square/round/circle | N
size | String | medium | 组件尺寸。可选项extra-small/small/medium/large。TS 类型:`SizeEnum` | N
suffix | Slot | - | 右侧内容,可用于定义右侧图标 | N
theme | String | default | 组件风格依次为品牌色、危险色。可选项default/primary/danger/light | N
type | String | - | 同小程序的 formType。可选项submit/reset | N
variant | String | base | 按钮形式基础、线框、文字。可选项base/outline/dashed/text | N
open-type | String | - | 微信开放能力。<br />具体释义:<br />`contact` 打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息,<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/customer-message/customer-message.html">具体说明</a> *小程序插件中不能使用*<br />`share` 触发用户转发,使用前建议先阅读<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share.html#使用指引">使用指引</a><br />`getPhoneNumber` 获取用户手机号,可以从 bindgetphonenumber 回调中获取到用户信息,<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html">具体说明</a> *小程序插件中不能使用*<br />`getUserInfo` 获取用户信息,可以从 bindgetuserinfo 回调中获取到用户信息 *小程序插件中不能使用*<br />`launchApp` 打开APP可以通过 app-parameter 属性设定向 APP 传的参数<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/launchApp.html">具体说明</a><br />`openSetting` 打开授权设置页;<br />`feedback` 打开“意见反馈”页面,用户可提交反馈内容并上传<a href="https://developers.weixin.qq.com/miniprogram/dev/api/base/debug/wx.getLogManager.html">日志</a>,开发者可以登录<a href="https://mp.weixin.qq.com/">小程序管理后台</a>后进入左侧菜单“客服反馈”页面获取到反馈内容;<br />`chooseAvatar` 获取用户头像,可以从 bindchooseavatar 回调中获取到头像信息。<br />[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html)。可选项contact/share/getPhoneNumber/getUserInfo/launchApp/openSetting/feedback/chooseAvatar | N
hover-class | String | '' | 指定按钮按下去的样式类,按钮不为加载或禁用状态时有效。当 `hover-class="none"` 时,没有点击态效果 | N
hover-stop-propagation | Boolean | false | 指定是否阻止本节点的祖先节点出现点击态 | N
hover-start-time | Number | 20 | 按住后多久出现点击态,单位毫秒 | N
hover-stay-time | Number | 70 | 手指松开后点击态保留时间,单位毫秒 | N
lang | String | en | 指定返回用户信息的语言zh_CN 简体中文zh_TW 繁体中文en 英文。。<br />具体释义:<br />`en` 英文;<br />`zh_CN` 简体中文;<br />`zh_TW` 繁体中文。<br />[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html)。可选项en/zh_CN/zh_TW | N
session-from | String | - | 会话来源open-type="contact"时有效 | N
send-message-title | String | 当前标题 | 会话内消息卡片标题open-type="contact"时有效 | N
send-message-path | String | 当前分享路径 | 会话内消息卡片点击跳转小程序路径open-type="contact"时有效 | N
send-message-img | String | 截图 | 会话内消息卡片图片open-type="contact"时有效 | N
app-parameter | String | - | 打开 APP 时,向 APP 传递的参数open-type=launchApp时有效 | N
show-message-card | Boolean | false | 是否显示会话内消息卡片,设置此参数为 true用户进入客服会话会在右下角显示"可能要发送的小程序"提示用户点击后可以快速发送小程序消息open-type="contact"时有效 | N
bindgetuserinfo | Eventhandle | - | 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与<a href="https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserInfo.html">wx.getUserInfo</a>返回的一致open-type="getUserInfo"时有效 | N
bindcontact | Eventhandle | - | 客服消息回调open-type="contact"时有效 | N
bindgetphonenumber | Eventhandle | - | 获取用户手机号回调open-type=getPhoneNumber时有效 | N
binderror | Eventhandle | - | 当使用开放能力时发生错误的回调open-type=launchApp时有效 | N
bindopensetting | Eventhandle | - | 在打开授权设置页后回调open-type=openSetting时有效 | N
bindlaunchapp | Eventhandle | - | 打开 APP 成功的回调open-type=launchApp时有效 | N
bindchooseavatar | Eventhandle | - | 获取用户头像回调open-type=chooseAvatar时有效 | N
### Button Events
名称 | 参数 | 描述
-- | -- | --
tap | `event` | 点击按钮,当按钮不为加载或禁用状态时触发
### Button 外部样式类
类名 | 说明
-- | --
t-class | 根节点样式类
t-class-icon | 图标样式类
t-class-loading | 加载样式类
### CSS 变量
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-button-border-radius | @radius-default | -
--td-button-border-width | 4rpx | -
--td-button-danger-active-bg-color | @error-color-7 | -
--td-button-danger-active-border-color | @error-color-7 | -
--td-button-danger-bg-color | @error-color | -
--td-button-danger-border-color | @error-color | -
--td-button-danger-color | @font-white-1 | -
--td-button-danger-dashed-border-color | @button-danger-dashed-color | -
--td-button-danger-dashed-color | @error-color | -
--td-button-danger-dashed-disabled-color | @button-danger-disabled-color | -
--td-button-danger-disabled-bg | @error-color-3 | -
--td-button-danger-disabled-border-color | @error-color-3 | -
--td-button-danger-disabled-color | @font-white-1 | -
--td-button-danger-outline-active-bg-color | @bg-color-container-active | -
--td-button-danger-outline-active-border-color | @error-color-7 | -
--td-button-danger-outline-border-color | @button-danger-outline-color | -
--td-button-danger-outline-color | @error-color | -
--td-button-danger-outline-disabled-color | @error-color-3 | -
--td-button-danger-text-active-bg-color | @bg-color-container-active | -
--td-button-danger-text-color | @error-color | -
--td-button-danger-text-disabled-color | @button-danger-disabled-color | -
--td-button-default-active-bg-color | @bg-color-component-active | -
--td-button-default-active-border-color | @bg-color-component-active | -
--td-button-default-bg-color | @bg-color-component | -
--td-button-default-border-color | @bg-color-component | -
--td-button-default-color | @font-gray-1 | -
--td-button-default-disabled-bg | @bg-color-component-disabled | -
--td-button-default-disabled-border-color | @bg-color-component-disabled | -
--td-button-default-disabled-color | @font-gray-4 | -
--td-button-default-outline-active-bg-color | @bg-color-container-active | -
--td-button-default-outline-active-border-color | @component-border | -
--td-button-default-outline-border-color | @component-border | -
--td-button-default-outline-color | @font-gray-1 | -
--td-button-default-outline-disabled-color | @component-border | -
--td-button-default-text-active-bg-color | @bg-color-container-active | -
--td-button-extra-small-font-size | @font-size-base | -
--td-button-extra-small-height | 56rpx | -
--td-button-extra-small-icon-font-size | 36rpx | -
--td-button-extra-small-padding-horizontal | 16rpx | -
--td-button-font-weight | 600 | -
--td-button-ghost-border-color | @button-ghost-color | -
--td-button-ghost-color | @bg-color-container | -
--td-button-ghost-danger-border-color | @error-color | -
--td-button-ghost-danger-color | @error-color | -
--td-button-ghost-disabled-color | rgba(255, 255, 255, 0.35) | -
--td-button-ghost-primary-border-color | @brand-color | -
--td-button-ghost-primary-color | @brand-color | -
--td-button-icon-border-radius | 8rpx | -
--td-button-icon-spacer | @spacer | -
--td-button-large-font-size | @font-size-m | -
--td-button-large-height | 96rpx | -
--td-button-large-icon-font-size | 48rpx | -
--td-button-large-padding-horizontal | 40rpx | -
--td-button-light-active-bg-color | @brand-color-light-active | -
--td-button-light-active-border-color | @brand-color-light-active | -
--td-button-light-bg-color | @brand-color-light | -
--td-button-light-border-color | @brand-color-light | -
--td-button-light-color | @brand-color | -
--td-button-light-disabled-bg | @brand-color-light | -
--td-button-light-disabled-border-color | @brand-color-light | -
--td-button-light-disabled-color | @brand-color-disabled | -
--td-button-light-outline-active-bg-color | @brand-color-light-active | -
--td-button-light-outline-active-border-color | @brand-color-active | -
--td-button-light-outline-bg-color | @brand-color-light | -
--td-button-light-outline-border-color | @button-light-outline-color | -
--td-button-light-outline-color | @brand-color | -
--td-button-light-outline-disabled-color | @brand-color-disabled | -
--td-button-light-text-active-bg-color | @bg-color-container-active | -
--td-button-light-text-color | @brand-color | -
--td-button-medium-font-size | @font-size-m | -
--td-button-medium-height | 80rpx | -
--td-button-medium-icon-font-size | 40rpx | -
--td-button-medium-padding-horizontal | 32rpx | -
--td-button-primary-active-bg-color | @brand-color-active | -
--td-button-primary-active-border-color | @brand-color-active | -
--td-button-primary-bg-color | @brand-color | -
--td-button-primary-border-color | @brand-color | -
--td-button-primary-color | @font-white-1 | -
--td-button-primary-dashed-border-color | @button-primary-dashed-color | -
--td-button-primary-dashed-color | @brand-color | -
--td-button-primary-dashed-disabled-color | @brand-color-disabled | -
--td-button-primary-disabled-bg | @brand-color-disabled | -
--td-button-primary-disabled-border-color | @brand-color-disabled | -
--td-button-primary-disabled-color | @font-white-1 | -
--td-button-primary-outline-active-bg-color | @bg-color-container-active | -
--td-button-primary-outline-active-border-color | @brand-color-active | -
--td-button-primary-outline-border-color | @button-primary-outline-color | -
--td-button-primary-outline-color | @brand-color | -
--td-button-primary-outline-disabled-color | @brand-color-disabled | -
--td-button-primary-text-active-bg-color | @bg-color-container-active | -
--td-button-primary-text-color | @brand-color | -
--td-button-primary-text-disabled-color | @brand-color-disabled | -
--td-button-small-font-size | @font-size-base | -
--td-button-small-height | 64rpx | -
--td-button-small-icon-font-size | 36rpx | -
--td-button-small-padding-horizontal | 24rpx | -

View File

@ -0,0 +1,35 @@
import { SuperComponent } from '../common/src/index';
import type { TdButtonProps } from './type';
export interface ButtonProps extends TdButtonProps {
}
export default class Button extends SuperComponent {
externalClasses: string[];
behaviors: string[];
properties: TdButtonProps;
options: {
multipleSlots: boolean;
};
data: {
prefix: string;
className: string;
classPrefix: string;
};
observers: {
'theme, size, plain, block, shape, disabled, loading, variant'(): void;
icon(icon: any): void;
};
lifetimes: {
attached(): void;
};
methods: {
setClass(): void;
getuserinfo(e: any): void;
contact(e: any): void;
getphonenumber(e: any): void;
error(e: any): void;
opensetting(e: any): void;
launchapp(e: any): void;
chooseavatar(e: any): void;
handleTap(e: any): void;
};
}

View File

@ -0,0 +1,97 @@
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 { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import props from './props';
import { canIUseFormFieldButton } from '../common/version';
import { setIcon } from '../common/utils';
const { prefix } = config;
const name = `${prefix}-button`;
let Button = class Button extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`, `${prefix}-class-icon`, `${prefix}-class-loading`];
this.behaviors = canIUseFormFieldButton() ? ['wx://form-field-button'] : [];
this.properties = props;
this.options = {
multipleSlots: true,
};
this.data = {
prefix,
className: '',
classPrefix: name,
};
this.observers = {
'theme, size, plain, block, shape, disabled, loading, variant'() {
this.setClass();
},
icon(icon) {
const obj = setIcon('icon', icon, '');
this.setData(Object.assign({}, obj));
},
};
this.lifetimes = {
attached() {
this.setClass();
},
};
this.methods = {
setClass() {
const classList = [
name,
`${prefix}-class`,
`${name}--${this.data.variant || 'base'}`,
`${name}--${this.data.theme || 'default'}`,
`${name}--${this.data.shape || 'rectangle'}`,
`${name}--size-${this.data.size || 'medium'}`,
];
if (this.data.block) {
classList.push(`${name}--block`);
}
if (this.data.disabled) {
classList.push(`${name}--disabled`);
}
if (this.data.ghost) {
classList.push(`${name}--ghost`);
}
this.setData({
className: classList.join(' '),
});
},
getuserinfo(e) {
this.triggerEvent('getuserinfo', e.detail);
},
contact(e) {
this.triggerEvent('contact', e.detail);
},
getphonenumber(e) {
this.triggerEvent('getphonenumber', e.detail);
},
error(e) {
this.triggerEvent('error', e.detail);
},
opensetting(e) {
this.triggerEvent('opensetting', e.detail);
},
launchapp(e) {
this.triggerEvent('launchapp', e.detail);
},
chooseavatar(e) {
this.triggerEvent('chooseavatar', e.detail);
},
handleTap(e) {
if (this.data.disabled || this.data.loading)
return;
this.triggerEvent('tap', e);
},
};
}
};
Button = __decorate([
wxComponent()
], Button);
export default Button;

View File

@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"t-icon": "../icon/icon",
"t-loading": "../loading/loading"
}
}

View File

@ -0,0 +1,59 @@
<import src="../common/template/icon.wxml" />
<wxs src="../common/utils.wxs" module="_" />
<button
style="{{_._style([style, customStyle])}}"
data-custom="{{ customDataset }}"
class="class {{className}}"
form-type="{{disabled || loading ? '' : type}}"
open-type="{{disabled || loading ? '' : openType}}"
hover-stop-propagation="{{hoverStopPropagation}}"
hover-start-time="{{hoverStartTime}}"
hover-stay-time="{{hoverStayTime}}"
lang="{{lang}}"
session-from="{{sessionFrom}}"
hover-class="{{disabled || loading ? '' : (hoverClass || classPrefix + '--hover')}}"
send-message-title="{{sendMessageTitle}}"
send-message-path="{{sendMessagePath}}"
send-message-img="{{sendMessageImg}}"
app-parameter="{{appParameter}}"
show-message-card="{{showMessageCard}}"
catch:tap="handleTap"
bind:getuserinfo="getuserinfo"
bind:contact="contact"
bind:getphonenumber="getphonenumber"
bind:error="error"
bind:opensetting="opensetting"
bind:launchapp="launchapp"
bind:chooseavatar="chooseavatar"
aria-label="{{ariaLabel}}"
>
<template
wx:if="{{iconName || _.isNoEmptyObj(iconData)}}"
is="icon"
data="{{class: classPrefix + '__icon', tClass: prefix + '-class-icon', ariaHidden: true, name: iconName, ...iconData}}"
/>
<t-loading
wx:if="{{loading}}"
delay="{{loadingProps.delay || 0}}"
duration="{{loadingProps.duration || 800}}"
indicator="{{loadingProps.indicator || true}}"
inheritColor="{{loadingProps.inheritColor || true}}"
layout="{{loadingProps.layout || 'horizontal'}}"
pause="{{loadingProps.pause || false}}"
progress="{{loadingProps.progress || 0}}"
reverse="{{loadingProps.reverse || false}}"
size="{{loadingProps.size || '40rpx'}}"
text="{{loadingProps.text || '' }}"
theme="{{loadingProps.theme || 'circular'}}"
loading
t-class="{{classPrefix}}__loading {{classPrefix}}__loading--wrapper"
t-class-indicator="{{classPrefix}}__loading--indicator {{prefix}}-class-loading"
/>
<view class="{{classPrefix}}__content">
<slot name="content" />
<block>{{content}}</block>
<slot />
</view>
<slot name="suffix" />
</button>

View File

@ -0,0 +1,448 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-button--size-extra-small {
font-size: var(--td-button-extra-small-font-size, var(--td-font-size-base, 28rpx));
padding-left: var(--td-button-extra-small-padding-horizontal, 16rpx);
padding-right: var(--td-button-extra-small-padding-horizontal, 16rpx);
height: var(--td-button-extra-small-height, 56rpx);
line-height: var(--td-button-extra-small-height, 56rpx);
}
.t-button--size-extra-small .t-button__icon {
font-size: var(--td-button-extra-small-icon-font-size, 36rpx);
}
.t-button--size-small {
font-size: var(--td-button-small-font-size, var(--td-font-size-base, 28rpx));
padding-left: var(--td-button-small-padding-horizontal, 24rpx);
padding-right: var(--td-button-small-padding-horizontal, 24rpx);
height: var(--td-button-small-height, 64rpx);
line-height: var(--td-button-small-height, 64rpx);
}
.t-button--size-small .t-button__icon {
font-size: var(--td-button-small-icon-font-size, 36rpx);
}
.t-button--size-medium {
font-size: var(--td-button-medium-font-size, var(--td-font-size-m, 32rpx));
padding-left: var(--td-button-medium-padding-horizontal, 32rpx);
padding-right: var(--td-button-medium-padding-horizontal, 32rpx);
height: var(--td-button-medium-height, 80rpx);
line-height: var(--td-button-medium-height, 80rpx);
}
.t-button--size-medium .t-button__icon {
font-size: var(--td-button-medium-icon-font-size, 40rpx);
}
.t-button--size-large {
font-size: var(--td-button-large-font-size, var(--td-font-size-m, 32rpx));
padding-left: var(--td-button-large-padding-horizontal, 40rpx);
padding-right: var(--td-button-large-padding-horizontal, 40rpx);
height: var(--td-button-large-height, 96rpx);
line-height: var(--td-button-large-height, 96rpx);
}
.t-button--size-large .t-button__icon {
font-size: var(--td-button-large-icon-font-size, 48rpx);
}
.t-button--default {
color: var(--td-button-default-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
background-color: var(--td-button-default-bg-color, var(--td-bg-color-component, var(--td-gray-color-3, #e7e7e7)));
}
.t-button--default::after {
border-width: var(--td-button-border-width, 4rpx);
border-color: var(--td-button-default-border-color, var(--td-bg-color-component, var(--td-gray-color-3, #e7e7e7)));
}
.t-button--default.t-button--hover {
z-index: 0;
}
.t-button--default.t-button--hover::after {
background-color: var(--td-button-default-active-bg-color, var(--td-bg-color-component-active, var(--td-gray-color-6, #a6a6a6)));
border-color: var(--td-button-default-active-border-color, var(--td-bg-color-component-active, var(--td-gray-color-6, #a6a6a6)));
}
.t-button--default.t-button--disabled {
color: var(--td-button-default-disabled-color, var(--td-font-gray-4, rgba(0, 0, 0, 0.26)));
background-color: var(--td-button-default-disabled-bg, var(--td-bg-color-component-disabled, var(--td-gray-color-2, #eeeeee)));
}
.t-button--default.t-button--disabled::after {
border-color: var(--td-button-default-disabled-border-color, var(--td-bg-color-component-disabled, var(--td-gray-color-2, #eeeeee)));
}
.t-button--primary {
color: var(--td-button-primary-color, var(--td-font-white-1, #ffffff));
background-color: var(--td-button-primary-bg-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-button--primary::after {
border-width: var(--td-button-border-width, 4rpx);
border-color: var(--td-button-primary-border-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-button--primary.t-button--hover {
z-index: 0;
}
.t-button--primary.t-button--hover::after {
background-color: var(--td-button-primary-active-bg-color, var(--td-brand-color-active, var(--td-primary-color-8, #003cab)));
border-color: var(--td-button-primary-active-border-color, var(--td-brand-color-active, var(--td-primary-color-8, #003cab)));
}
.t-button--primary.t-button--disabled {
color: var(--td-button-primary-disabled-color, var(--td-font-white-1, #ffffff));
background-color: var(--td-button-primary-disabled-bg, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
}
.t-button--primary.t-button--disabled::after {
border-color: var(--td-button-primary-disabled-border-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
}
.t-button--light {
color: var(--td-button-light-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
background-color: var(--td-button-light-bg-color, var(--td-brand-color-light, var(--td-primary-color-1, #f2f3ff)));
}
.t-button--light::after {
border-width: var(--td-button-border-width, 4rpx);
border-color: var(--td-button-light-border-color, var(--td-brand-color-light, var(--td-primary-color-1, #f2f3ff)));
}
.t-button--light.t-button--hover {
z-index: 0;
}
.t-button--light.t-button--hover::after {
background-color: var(--td-button-light-active-bg-color, var(--td-brand-color-light-active, var(--td-primary-color-2, #d9e1ff)));
border-color: var(--td-button-light-active-border-color, var(--td-brand-color-light-active, var(--td-primary-color-2, #d9e1ff)));
}
.t-button--light.t-button--disabled {
color: var(--td-button-light-disabled-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
background-color: var(--td-button-light-disabled-bg, var(--td-brand-color-light, var(--td-primary-color-1, #f2f3ff)));
}
.t-button--light.t-button--disabled::after {
border-color: var(--td-button-light-disabled-border-color, var(--td-brand-color-light, var(--td-primary-color-1, #f2f3ff)));
}
.t-button--danger {
color: var(--td-button-danger-color, var(--td-font-white-1, #ffffff));
background-color: var(--td-button-danger-bg-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
}
.t-button--danger::after {
border-width: var(--td-button-border-width, 4rpx);
border-color: var(--td-button-danger-border-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
}
.t-button--danger.t-button--hover {
z-index: 0;
}
.t-button--danger.t-button--hover::after {
background-color: var(--td-button-danger-active-bg-color, var(--td-error-color-7, #ad352f));
border-color: var(--td-button-danger-active-border-color, var(--td-error-color-7, #ad352f));
}
.t-button--danger.t-button--disabled {
color: var(--td-button-danger-disabled-color, var(--td-font-white-1, #ffffff));
background-color: var(--td-button-danger-disabled-bg, var(--td-error-color-3, #ffb9b0));
}
.t-button--danger.t-button--disabled::after {
border-color: var(--td-button-danger-disabled-border-color, var(--td-error-color-3, #ffb9b0));
}
.t-button {
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;
white-space: nowrap;
text-align: center;
background-image: none;
transition: all 0.3s;
touch-action: manipulation;
border-radius: var(--td-button-border-radius, var(--td-radius-default, 12rpx));
outline: none;
font-family: PingFang SC, Microsoft YaHei, Arial Regular;
font-weight: var(--td-button-font-weight, 600);
vertical-align: top;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
-webkit-user-select: none;
user-select: none;
/* stylelint-disable-next-line */
-webkit-appearance: none;
}
.t-button::after {
border-radius: calc(var(--td-button-border-radius, var(--td-radius-default, 12rpx)) * 2);
}
.t-button--text {
color: var(--td-button-default-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
background: none;
}
.t-button--text::after {
border: 0;
}
.t-button--text.t-button--hover::after {
background-color: var(--td-button-default-text-active-bg-color, var(--td-bg-color-container-active, var(--td-gray-color-3, #e7e7e7)));
}
.t-button--text.t-button--primary {
color: var(--td-button-primary-text-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
background: none;
}
.t-button--text.t-button--primary.t-button--hover::after {
background-color: var(--td-button-primary-text-active-bg-color, var(--td-bg-color-container-active, var(--td-gray-color-3, #e7e7e7)));
}
.t-button--text.t-button--primary.t-button--disabled {
color: var(--td-button-primary-text-disabled-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
background: none;
}
.t-button--text.t-button--danger {
color: var(--td-button-danger-text-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
background: none;
}
.t-button--text.t-button--danger.t-button--hover::after {
background-color: var(--td-button-danger-text-active-bg-color, var(--td-bg-color-container-active, var(--td-gray-color-3, #e7e7e7)));
}
.t-button--text.t-button--danger.t-button--disabled {
color: var(--td-button-danger-text-disabled-color, var(--td-button-danger-disabled-color, var(--td-font-white-1, #ffffff)));
background: none;
}
.t-button--text.t-button--light {
color: var(--td-button-light-text-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
background: none;
}
.t-button--text.t-button--light.t-button--hover::after {
background-color: var(--td-button-light-text-active-bg-color, var(--td-bg-color-container-active, var(--td-gray-color-3, #e7e7e7)));
}
.t-button--text.t-button--disabled {
color: var(--td-button-default-disabled-color, var(--td-font-gray-4, rgba(0, 0, 0, 0.26)));
}
.t-button--ghost {
background-color: transparent;
color: var(--td-button-ghost-color, var(--td-bg-color-container, var(--td-font-white-1, #ffffff)));
}
.t-button--ghost::after {
border-color: var(--td-button-ghost-border-color, var(--td-button-ghost-color, var(--td-bg-color-container, var(--td-font-white-1, #ffffff))));
}
.t-button--ghost.t-button--hover::after {
background: none;
}
.t-button--ghost.t-button--primary {
color: var(--td-button-ghost-primary-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-button--ghost.t-button--primary::after {
border-color: var(--td-button-ghost-primary-border-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-button--ghost.t-button--danger {
color: var(--td-button-ghost-danger-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
}
.t-button--ghost.t-button--danger::after {
border-color: var(--td-button-ghost-danger-border-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
}
.t-button--ghost.t-button--disabled {
background-color: transparent;
color: var(--td-button-ghost-disabled-color, rgba(255, 255, 255, 0.35));
}
.t-button--ghost.t-button--disabled::after {
border-color: var(--td-button-ghost-disabled-color, rgba(255, 255, 255, 0.35));
}
.t-button--outline {
color: var(--td-button-default-outline-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
background-color: transparent;
}
.t-button--outline::after {
border-color: var(--td-button-default-outline-border-color, var(--td-component-border, var(--td-gray-color-4, #dcdcdc)));
}
.t-button--outline.t-button--hover::after {
background-color: var(--td-button-default-outline-active-bg-color, var(--td-bg-color-container-active, var(--td-gray-color-3, #e7e7e7)));
border-color: var(--td-button-default-outline-active-border-color, var(--td-component-border, var(--td-gray-color-4, #dcdcdc)));
}
.t-button--outline.t-button--disabled {
color: var(--td-button-default-outline-disabled-color, var(--td-component-border, var(--td-gray-color-4, #dcdcdc)));
}
.t-button--outline.t-button--disabled::after {
border-color: var(--td-button-default-outline-disabled-color, var(--td-component-border, var(--td-gray-color-4, #dcdcdc)));
}
.t-button--outline.t-button--primary {
color: var(--td-button-primary-outline-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-button--outline.t-button--primary::after {
border-color: var(--td-button-primary-outline-border-color, var(--td-button-primary-outline-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9))));
}
.t-button--outline.t-button--primary.t-button--hover {
color: var(--td-button-primary-outline-active-border-color, var(--td-brand-color-active, var(--td-primary-color-8, #003cab)));
}
.t-button--outline.t-button--primary.t-button--hover::after {
background-color: var(--td-button-primary-outline-active-bg-color, var(--td-bg-color-container-active, var(--td-gray-color-3, #e7e7e7)));
border-color: var(--td-button-primary-outline-active-border-color, var(--td-brand-color-active, var(--td-primary-color-8, #003cab)));
}
.t-button--outline.t-button--primary.t-button--disabled {
background-color: transparent;
color: var(--td-button-primary-outline-disabled-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
}
.t-button--outline.t-button--primary.t-button--disabled::after {
border-color: var(--td-button-primary-outline-disabled-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
}
.t-button--outline.t-button--danger {
color: var(--td-button-danger-outline-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
}
.t-button--outline.t-button--danger::after {
border-color: var(--td-button-danger-outline-border-color, var(--td-button-danger-outline-color, var(--td-error-color, var(--td-error-color-6, #d54941))));
}
.t-button--outline.t-button--danger.t-button--hover {
color: var(--td-button-danger-outline-active-border-color, var(--td-error-color-7, #ad352f));
}
.t-button--outline.t-button--danger.t-button--hover::after {
background-color: var(--td-button-danger-outline-active-bg-color, var(--td-bg-color-container-active, var(--td-gray-color-3, #e7e7e7)));
border-color: var(--td-button-danger-outline-active-border-color, var(--td-error-color-7, #ad352f));
}
.t-button--outline.t-button--danger.t-button--disabled {
background-color: transparent;
color: var(--td-button-danger-outline-disabled-color, var(--td-error-color-3, #ffb9b0));
}
.t-button--outline.t-button--danger.t-button--disabled::after {
border-color: var(--td-button-danger-outline-disabled-color, var(--td-error-color-3, #ffb9b0));
}
.t-button--outline.t-button--light {
color: var(--td-button-light-outline-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
background-color: var(--td-button-light-outline-bg-color, var(--td-brand-color-light, var(--td-primary-color-1, #f2f3ff)));
}
.t-button--outline.t-button--light::after {
border-color: var(--td-button-light-outline-border-color, var(--td-button-light-outline-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9))));
}
.t-button--outline.t-button--light.t-button--hover {
color: var(--td-button-light-outline-active-border-color, var(--td-brand-color-active, var(--td-primary-color-8, #003cab)));
}
.t-button--outline.t-button--light.t-button--hover::after {
background-color: var(--td-button-light-outline-active-bg-color, var(--td-brand-color-light-active, var(--td-primary-color-2, #d9e1ff)));
border-color: var(--td-button-light-outline-active-border-color, var(--td-brand-color-active, var(--td-primary-color-8, #003cab)));
}
.t-button--outline.t-button--light.t-button--disabled {
background-color: transparent;
color: var(--td-button-light-outline-disabled-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
}
.t-button--outline.t-button--light.t-button--disabled::after {
border-color: var(--td-button-light-outline-disabled-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
}
.t-button--dashed {
background-color: transparent;
border-style: dashed;
}
.t-button--dashed.t-button--primary {
color: var(--td-button-primary-dashed-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-button--dashed.t-button--primary::after {
border-color: var(--td-button-primary-dashed-border-color, var(--td-button-primary-dashed-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9))));
}
.t-button--dashed.t-button--primary.t-button--disabled {
background-color: transparent;
color: var(--td-button-primary-dashed-disabled-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
}
.t-button--dashed.t-button--primary.t-button--disabled::after {
border-color: var(--td-button-primary-dashed-disabled-color, var(--td-brand-color-disabled, var(--td-primary-color-3, #b5c7ff)));
}
.t-button--dashed.t-button--danger {
color: var(--td-button-danger-dashed-color, var(--td-error-color, var(--td-error-color-6, #d54941)));
}
.t-button--dashed.t-button--danger::after {
border-color: var(--td-button-danger-dashed-border-color, var(--td-button-danger-dashed-color, var(--td-error-color, var(--td-error-color-6, #d54941))));
}
.t-button--dashed.t-button--danger.t-button--disabled {
background-color: transparent;
color: var(--td-button-danger-dashed-disabled-color, var(--td-button-danger-disabled-color, var(--td-font-white-1, #ffffff)));
}
.t-button--dashed.t-button--danger.t-button--disabled::after {
border-color: var(--td-button-danger-dashed-disabled-color, var(--td-button-danger-disabled-color, var(--td-font-white-1, #ffffff)));
}
.t-button__loading + .t-button__content:not(:empty),
.t-button__icon + .t-button__content:not(:empty) {
margin-left: 8rpx;
}
.t-button__icon {
border-radius: var(--td-button-icon-border-radius, 8rpx);
}
.t-button--round.t-button--size-large {
border-radius: calc(var(--td-button-large-height, 96rpx) / 2);
}
.t-button--round.t-button--size-large::after {
border-radius: var(--td-button-large-height, 96rpx);
}
.t-button--round.t-button--size-medium {
border-radius: calc(var(--td-button-medium-height, 80rpx) / 2);
}
.t-button--round.t-button--size-medium::after {
border-radius: var(--td-button-medium-height, 80rpx);
}
.t-button--round.t-button--size-small {
border-radius: calc(var(--td-button-small-height, 64rpx) / 2);
}
.t-button--round.t-button--size-small::after {
border-radius: var(--td-button-small-height, 64rpx);
}
.t-button--round.t-button--size-extra-small {
border-radius: calc(var(--td-button-extra-small-height, 56rpx) / 2);
}
.t-button--round.t-button--size-extra-small::after {
border-radius: var(--td-button-extra-small-height, 56rpx);
}
.t-button--square {
padding: 0;
}
.t-button--square.t-button--size-large {
width: var(--td-button-large-height, 96rpx);
}
.t-button--square.t-button--size-medium {
width: var(--td-button-medium-height, 80rpx);
}
.t-button--square.t-button--size-small {
width: var(--td-button-small-height, 64rpx);
}
.t-button--square.t-button--size-extra-small {
width: var(--td-button-extra-small-height, 56rpx);
}
.t-button--circle {
padding: 0;
border-radius: 50%;
}
.t-button--circle.t-button--size-large {
width: var(--td-button-large-height, 96rpx);
}
.t-button--circle.t-button--size-large::after {
border-radius: 50%;
}
.t-button--circle.t-button--size-medium {
width: var(--td-button-medium-height, 80rpx);
}
.t-button--circle.t-button--size-medium::after {
border-radius: 50%;
}
.t-button--circle.t-button--size-small {
width: var(--td-button-small-height, 64rpx);
}
.t-button--circle.t-button--size-small::after {
border-radius: 50%;
}
.t-button--circle.t-button--size-extra-small {
width: var(--td-button-extra-small-height, 56rpx);
}
.t-button--circle.t-button--size-extra-small::after {
border-radius: 50%;
}
.t-button--block {
display: flex;
width: 100%;
}
.t-button--disabled {
cursor: not-allowed;
}
.t-button__loading--wrapper {
display: flex;
align-items: center;
justify-content: center;
}
.t-button.t-button--hover::after {
z-index: -1;
}

View File

@ -0,0 +1,3 @@
export * from './props';
export * from './type';
export * from './button';

View File

@ -0,0 +1,3 @@
export * from './props';
export * from './type';
export * from './button';

View File

@ -0,0 +1,3 @@
import { TdButtonProps } from './type';
declare const props: TdButtonProps;
export default props;

View File

@ -0,0 +1,100 @@
const props = {
block: {
type: Boolean,
value: false,
},
content: {
type: String,
},
customDataset: {
type: null,
},
disabled: {
type: Boolean,
value: false,
},
externalClasses: {
type: Array,
},
ghost: {
type: Boolean,
value: false,
},
icon: {
type: null,
},
loading: {
type: Boolean,
value: false,
},
loadingProps: {
type: Object,
},
shape: {
type: String,
value: 'rectangle',
},
size: {
type: String,
value: 'medium',
},
theme: {
type: String,
value: 'default',
},
type: {
type: String,
},
variant: {
type: String,
value: 'base',
},
openType: {
type: String,
},
hoverClass: {
type: String,
value: '',
},
hoverStopPropagation: {
type: Boolean,
value: false,
},
hoverStartTime: {
type: Number,
value: 20,
},
hoverStayTime: {
type: Number,
value: 70,
},
lang: {
type: String,
value: 'en',
},
sessionFrom: {
type: String,
value: '',
},
sendMessageTitle: {
type: String,
value: '',
},
sendMessagePath: {
type: String,
value: '',
},
sendMessageImg: {
type: String,
value: '',
},
appParameter: {
type: String,
value: '',
},
showMessageCard: {
type: Boolean,
value: false,
},
};
export default props;

View File

@ -0,0 +1,108 @@
import { LoadingProps } from '../loading/index';
import { SizeEnum } from '../common/common';
export interface TdButtonProps {
block?: {
type: BooleanConstructor;
value?: boolean;
};
content?: {
type: StringConstructor;
value?: string;
};
customDataset?: {
type: ObjectConstructor;
value?: any;
};
disabled?: {
type: BooleanConstructor;
value?: boolean;
};
externalClasses?: {
type: ArrayConstructor;
value?: ['t-class', 't-class-icon', 't-class-loading'];
};
ghost?: {
type: BooleanConstructor;
value?: boolean;
};
icon?: {
type: null;
value?: string | object;
};
loading?: {
type: BooleanConstructor;
value?: boolean;
};
loadingProps?: {
type: ObjectConstructor;
value?: LoadingProps;
};
shape?: {
type: StringConstructor;
value?: 'rectangle' | 'square' | 'round' | 'circle';
};
size?: {
type: StringConstructor;
value?: SizeEnum;
};
theme?: {
type: StringConstructor;
value?: 'default' | 'primary' | 'danger';
};
type?: {
type: StringConstructor;
value?: 'submit' | 'reset';
};
variant?: {
type: StringConstructor;
value?: 'base' | 'outline' | 'text';
};
openType?: {
type: StringConstructor;
value?: 'contact' | 'share' | 'getPhoneNumber' | 'getUserInfo' | 'launchApp' | 'openSetting' | 'feedback' | 'chooseAvatar';
};
hoverClass?: {
type: StringConstructor;
value?: string;
};
hoverStopPropagation?: {
type: BooleanConstructor;
value?: boolean;
};
hoverStartTime?: {
type: NumberConstructor;
value?: number;
};
hoverStayTime?: {
type: NumberConstructor;
value?: number;
};
lang?: {
type: StringConstructor;
value?: 'en' | 'zh_CN' | 'zh_TW';
};
sessionFrom?: {
type: StringConstructor;
value?: string;
};
sendMessageTitle?: {
type: StringConstructor;
value?: string;
};
sendMessagePath?: {
type: StringConstructor;
value?: string;
};
sendMessageImg?: {
type: StringConstructor;
value?: string;
};
appParameter?: {
type: StringConstructor;
value?: string;
};
showMessageCard?: {
type: BooleanConstructor;
value?: boolean;
};
}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,44 @@
:: BASE_DOC ::
## API
### Calendar Props
name | type | default | description | required
-- | -- | -- | -- | --
auto-close | Boolean | true | `0.34.0` | N
confirm-btn | String / Object / Slot | '' | [see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/calendar/type.ts) | N
first-day-of-week | Number | 0 | \- | N
format | Function | - | Typescript`CalendarFormatType ` `type CalendarFormatType = (day: TDate) => TDate` `type TDateType = 'selected' \| 'disabled' \| 'start' \| 'centre' \| 'end' \| ''` `interface TDate { date: Date; day: number; type: TDateType; className?: string; prefix?: string; suffix?: string;}`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/calendar/type.ts) | N
max-date | Number | - | \- | N
min-date | Number | - | \- | N
title | String / Slot | - | \- | N
type | String | single | optionssingle/multiple/range | N
use-popup | Boolean | true | `0.32.0` | N
value | Number / Array | - | Typescript`number \| number[]` | N
default-value | Number / Array | undefined | uncontrolled property。Typescript`number \| number[]` | N
visible | Boolean | false | \- | N
### Calendar Events
name | params | description
-- | -- | --
change | `(value: timestamp)` | `0.28.0`
close | `(trigger: CalendarTrigger)` | `0.34.0`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/calendar/type.ts)。<br/>`type CalendarTrigger = 'close-btn' \| 'confirm-btn' \| 'overlay'`<br/>
confirm | `(value: timestamp)` | \-
select | `(value: timestamp)` | `0.28.0`
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-calendar-active-color | @brand-color | -
--td-calendar-bg-color | @bg-color-container | -
--td-calendar-days-color | @font-gray-2 | -
--td-calendar-item-centre-color | @brand-color-light | -
--td-calendar-item-disabled-color | @font-gray-4 | -
--td-calendar-item-suffix-color | @font-gray-3 | -
--td-calendar-radius | 24rpx | -
--td-calendar-selected-color | @font-white-1 | -
--td-calendar-title-color | @font-gray-1 | -
--td-calendar-title-font-size | 18px | -

View File

@ -0,0 +1,96 @@
---
title: Calendar 日历
description: 按照日历形式展示数据或日期的容器。
spline: form
isComponent: true
---
<span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20lines-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20functions-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20statements-100%25-blue" /></span><span class="coverages-badge" style="margin-right: 10px"><img src="https://img.shields.io/badge/coverages%3A%20branches-100%25-blue" /></span>
<div style="background: #ecf2fe; display: flex; align-items: center; line-height: 20px; padding: 14px 24px; border-radius: 3px; color: #555a65">
<svg fill="none" viewBox="0 0 16 16" width="16px" height="16px" style="margin-right: 5px">
<path fill="#0052d9" d="M8 15A7 7 0 108 1a7 7 0 000 14zM7.4 4h1.2v1.2H7.4V4zm.1 2.5h1V12h-1V6.5z" fillOpacity="0.9"></path>
</svg>
该组件于 0.22.0 版本上线,请留意版本。
</div>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-calendar": "tdesign-miniprogram/calendar/calendar"
}
```
## 代码演示
### 组件类型
#### 单个选择日期
{{ base }}
#### 多个选择日期
{{ multiple }}
#### 区间选择日期
{{ range }}
### 组件样式
#### 自定义文案
{{ custom-text }}
#### 自定义区间
{{ custom-range }}
#### 不使用 Popup
{{ without-popup }}
## API
### Calendar Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
auto-close | Boolean | true | `0.34.0`。自动关闭;在点击关闭按钮、确认按钮、遮罩层时自动关闭,不需要手动设置 visible | N
confirm-btn | String / Object / Slot | '' | 确认按钮。值为 null 则不显示确认按钮。值类型为字符串,则表示自定义按钮文本,值类型为 Object 则表示透传 Button 组件属性。。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/calendar/type.ts) | N
first-day-of-week | Number | 0 | 第一天从星期几开始,默认 0 = 周日 | N
format | Function | - | 用于格式化日期的函数。TS 类型:`CalendarFormatType ` `type CalendarFormatType = (day: TDate) => TDate` `type TDateType = 'selected' \| 'disabled' \| 'start' \| 'centre' \| 'end' \| ''` `interface TDate { date: Date; day: number; type: TDateType; className?: string; prefix?: string; suffix?: string;}`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/calendar/type.ts) | N
max-date | Number | - | 最大可选的日期,不传则默认半年后 | N
min-date | Number | - | 最小可选的日期,不传则默认今天 | N
title | String / Slot | - | 标题,不传默认为“请选择日期” | N
type | String | single | 日历的选择类型single = 单选multiple = 多选; range = 区间选择。可选项single/multiple/range | N
use-popup | Boolean | true | `0.32.0`。是否使用弹出层包裹日历 | N
value | Number / Array | - | 当前选择的日期,不传则默认今天,当 type = multiple 或 range 时传入数组。TS 类型:`number \| number[]` | N
default-value | Number / Array | undefined | 当前选择的日期,不传则默认今天,当 type = multiple 或 range 时传入数组。非受控属性。TS 类型:`number \| number[]` | N
visible | Boolean | false | 是否显示日历;`usePopup` 为 true 时有效 | N
### Calendar Events
名称 | 参数 | 描述
-- | -- | --
change | `(value: timestamp)` | `0.28.0`。不显示 confirm-btn 时,完成选择时触发(暂不支持 type = multiple
close | `(trigger: CalendarTrigger)` | `0.34.0`。关闭按钮时触发。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/calendar/type.ts)。<br/>`type CalendarTrigger = 'close-btn' \| 'confirm-btn' \| 'overlay'`<br/>
confirm | `(value: timestamp)` | 点击确认按钮时触发
select | `(value: timestamp)` | `0.28.0`。点击日期时触发
### CSS 变量
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-calendar-active-color | @brand-color | -
--td-calendar-bg-color | @bg-color-container | -
--td-calendar-days-color | @font-gray-2 | -
--td-calendar-item-centre-color | @brand-color-light | -
--td-calendar-item-disabled-color | @font-gray-4 | -
--td-calendar-item-suffix-color | @font-gray-3 | -
--td-calendar-radius | 24rpx | -
--td-calendar-selected-color | @font-white-1 | -
--td-calendar-title-color | @font-gray-1 | -
--td-calendar-title-font-size | 18px | -

View File

@ -0,0 +1,46 @@
/// <reference types="miniprogram-api-typings" />
import { SuperComponent } from '../common/src/index';
import { TdCalendarProps } from './type';
export interface CalendarProps extends TdCalendarProps {
}
export default class Calendar extends SuperComponent {
externalClasses: string[];
options: WechatMiniprogram.Component.ComponentOptions;
properties: TdCalendarProps;
data: {
prefix: string;
classPrefix: string;
months: any[];
scrollIntoView: string;
innerConfirmBtn: {
content: string;
};
};
controlledProps: {
key: string;
event: string;
}[];
lifetimes: {
created(): void;
ready(): void;
};
observers: {
type(v: any): void;
confirmBtn(v: any): void;
'firstDayOfWeek,minDate,maxDate'(firstDayOfWeek: any, minDate: any, maxDate: any): void;
value(v: any): void;
visible(v: any): void;
format(v: any): void;
};
methods: {
initialValue(): void;
scrollIntoView(): void;
calcMonths(): void;
close(trigger: any): void;
onVisibleChange(): void;
handleClose(): void;
handleSelect(e: any): void;
onTplButtonTap(): void;
toTime(val: any): any;
};
}

View File

@ -0,0 +1,167 @@
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 { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import props from './props';
import TCalendar from '../common/shared/calendar/index';
const { prefix } = config;
const name = `${prefix}-calendar`;
let Calendar = class Calendar extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`];
this.options = {
multipleSlots: true,
styleIsolation: 'apply-shared',
};
this.properties = props;
this.data = {
prefix,
classPrefix: name,
months: [],
scrollIntoView: '',
innerConfirmBtn: { content: '确定' },
};
this.controlledProps = [
{
key: 'value',
event: 'confirm',
},
{
key: 'value',
event: 'change',
},
];
this.lifetimes = {
created() {
this.base = new TCalendar(this.properties);
},
ready() {
this.initialValue();
this.setData({
days: this.base.getDays(),
});
this.calcMonths();
if (!this.data.usePopup) {
this.scrollIntoView();
}
},
};
this.observers = {
type(v) {
this.base.type = v;
},
confirmBtn(v) {
if (typeof v === 'string') {
this.setData({ innerConfirmBtn: v === 'slot' ? 'slot' : { content: v } });
}
else if (typeof v === 'object') {
this.setData({ innerConfirmBtn: v });
}
},
'firstDayOfWeek,minDate,maxDate'(firstDayOfWeek, minDate, maxDate) {
firstDayOfWeek && (this.base.firstDayOfWeek = firstDayOfWeek);
minDate && (this.base.minDate = minDate);
maxDate && (this.base.maxDate = maxDate);
this.calcMonths();
},
value(v) {
this.base.value = v;
},
visible(v) {
if (v) {
this.scrollIntoView();
this.base.value = this.data.value;
this.calcMonths();
}
},
format(v) {
this.base.format = v;
if (!this.data.usePopup) {
this.calcMonths();
}
},
};
this.methods = {
initialValue() {
const { value, type, minDate } = this.data;
if (!value) {
const today = new Date();
const now = minDate || new Date(today.getFullYear(), today.getMonth(), today.getDate()).getTime();
const initialValue = type === 'single' ? now : [now];
if (type === 'range') {
initialValue[1] = now + 24 * 3600 * 1000;
}
this.setData({
value: initialValue,
});
this.base.value = initialValue;
}
},
scrollIntoView() {
const { value } = this.data;
if (!value)
return;
const date = new Date(Array.isArray(value) ? value[0] : value);
if (date) {
this.setData({
scrollIntoView: `year_${date.getFullYear()}_month_${date.getMonth()}`,
});
}
},
calcMonths() {
const months = this.base.getMonths();
this.setData({
months,
});
},
close(trigger) {
if (this.data.autoClose) {
this.setData({ visible: false });
}
this.triggerEvent('close', { trigger });
},
onVisibleChange() {
this.close('overlay');
},
handleClose() {
this.close('close-btn');
},
handleSelect(e) {
const { date, year, month } = e.currentTarget.dataset;
if (date.type === 'disabled')
return;
const rawValue = this.base.select({ cellType: date.type, year, month, date: date.day });
const value = this.toTime(rawValue);
this.calcMonths();
if (this.data.confirmBtn == null) {
if (this.data.type === 'single' || rawValue.length === 2) {
this.setData({ visible: false });
this._trigger('change', { value });
}
}
this.triggerEvent('select', { value });
},
onTplButtonTap() {
const rawValue = this.base.getTrimValue();
const value = this.toTime(rawValue);
this.close('confirm-btn');
this._trigger('confirm', { value });
},
toTime(val) {
if (Array.isArray(val)) {
return val.map((item) => item.getTime());
}
return val.getTime();
},
};
}
};
Calendar = __decorate([
wxComponent()
], Calendar);
export default Calendar;

View File

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {
"t-popup": "../popup/popup",
"t-button": "../button/button",
"t-icon": "../icon/icon"
}
}

View File

@ -0,0 +1,13 @@
<wxs src="./calendar.wxs" module="this" />
<wxs src="../common/utils.wxs" module="_" />
<t-popup
wx:if="{{usePopup}}"
class="class"
visible="{{visible}}"
bind:visible-change="onVisibleChange"
placement="bottom"
>
<include src="./template.wxml" />
</t-popup>
<include wx:else src="./template.wxml" />

View File

@ -0,0 +1,30 @@
function getDateLabel(monthItem, dateItem) {
var weekdayText = ['日', '一', '二', '三', '四', '五', '六'];
var weekday = (monthItem.weekdayOfFirstDay + dateItem.day - 1) % 7;
var label = monthItem.month + 1 + '月' + dateItem.day + '日, 星期' + weekdayText[weekday];
if (dateItem.type === 'start') {
label = '开始日期:' + label;
}
if (dateItem.type === 'end') {
label = '结束日期:' + label;
}
if (isDateSelected(dateItem)) {
label = '已选中, ' + label;
}
if (dateItem.prefix) {
label += ', ' + dateItem.prefix;
}
if (dateItem.suffix) {
label += ', ' + dateItem.suffix;
}
return label;
}
function isDateSelected(dateItem) {
return ['start', 'end', 'selected', 'centre'].indexOf(dateItem.type) >= 0;
}
module.exports = {
getDateLabel: getDateLabel,
isDateSelected: isDateSelected,
};

View File

@ -0,0 +1,187 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-calendar {
position: relative;
z-index: 9999;
background: var(--td-calendar-bg-color, var(--td-bg-color-container, var(--td-font-white-1, #ffffff)));
overflow-x: hidden;
}
.t-calendar--popup {
border-top-left-radius: var(--td-calendar-radius, 24rpx);
border-top-right-radius: var(--td-calendar-radius, 24rpx);
}
.t-calendar__title {
display: flex;
align-items: center;
justify-content: center;
font-size: var(--td-calendar-title-font-size, 18px);
font-weight: 600;
color: var(--td-calendar-title-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
height: 52rpx;
padding: 32rpx;
}
.t-calendar__title:focus {
outline: 0;
}
.t-calendar__close-btn {
position: absolute;
top: 32rpx;
right: 32rpx;
margin: -24rpx;
padding: 24rpx;
}
.t-calendar__days {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-column-gap: 8rpx;
padding: 0 32rpx;
text-align: center;
line-height: 92rpx;
}
.t-calendar__days-item {
height: 92rpx;
font-size: 28rpx;
color: var(--td-calendar-days-color, var(--td-font-gray-2, rgba(0, 0, 0, 0.6)));
}
.t-calendar__content {
min-height: 400rpx;
display: flex;
flex-direction: column;
}
.t-calendar__month {
font-size: 28rpx;
color: var(--td-calendar-title-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
font-weight: 600;
padding: 32rpx 0 0;
}
.t-calendar__months {
height: 60vh;
padding: 0 32rpx 32rpx;
box-sizing: border-box;
}
.t-calendar__months::-webkit-scrollbar {
display: none;
}
.t-calendar__dates {
flex: 1;
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-column-gap: 8rpx;
}
.t-calendar__dates-item {
position: relative;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
border-radius: 16rpx;
height: 120rpx;
line-height: 48rpx;
font-weight: 600;
margin-top: 16rpx;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
-webkit-user-select: none;
user-select: none;
}
.t-calendar__dates-item-prefix,
.t-calendar__dates-item-suffix {
position: absolute;
font-size: 20rpx;
line-height: 32rpx;
width: 100%;
text-align: center;
font-weight: 400;
}
.t-calendar__dates-item-prefix {
top: 8rpx;
}
.t-calendar__dates-item-suffix {
bottom: 8rpx;
color: var(--td-calendar-item-suffix-color, var(--td-font-gray-3, rgba(0, 0, 0, 0.4)));
}
.t-calendar__dates-item-suffix--selected,
.t-calendar__dates-item-suffix--start,
.t-calendar__dates-item-suffix--end {
color: var(--td-calendar-selected-color, var(--td-font-white-1, #ffffff));
}
.t-calendar__dates-item-suffix--disabled {
color: var(--td-calendar-item-disabled-color, var(--td-font-gray-4, rgba(0, 0, 0, 0.26)));
}
.t-calendar__dates-item--selected,
.t-calendar__dates-item--start,
.t-calendar__dates-item--end {
background: var(--td-calendar-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
color: var(--td-calendar-selected-color, var(--td-font-white-1, #ffffff));
border-radius: 8rpx;
}
.t-calendar__dates-item--start {
border-radius: 8rpx 0 0 8rpx;
}
.t-calendar__dates-item--end {
border-radius: 0 8rpx 8rpx 0;
}
.t-calendar__dates-item--start + .t-calendar__dates-item--end::before {
content: '';
display: block;
position: absolute;
top: 0;
width: 8rpx;
height: 100%;
background: var(--td-calendar-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-calendar__dates-item--start + .t-calendar__dates-item--end:before {
left: -8rpx;
}
.t-calendar__dates-item--centre {
border-radius: 0;
background-color: var(--td-calendar-item-centre-color, var(--td-brand-color-light, var(--td-primary-color-1, #f2f3ff)));
}
.t-calendar__dates-item--centre::before,
.t-calendar__dates-item--centre::after {
content: '';
display: block;
position: absolute;
top: 0;
width: 8rpx;
height: 100%;
background-color: var(--td-calendar-item-centre-color, var(--td-brand-color-light, var(--td-primary-color-1, #f2f3ff)));
}
.t-calendar__dates-item--centre:before {
left: -8rpx;
}
.t-calendar__dates-item--centre:after {
right: -8rpx;
}
.t-calendar__dates-item--disabled {
color: var(--td-calendar-item-disabled-color, var(--td-font-gray-4, rgba(0, 0, 0, 0.26)));
cursor: default;
}
.t-calendar__footer {
padding: 32rpx;
}

View File

@ -0,0 +1,2 @@
export * from './type';
export * from './calendar';

View File

@ -0,0 +1,2 @@
export * from './type';
export * from './calendar';

View File

@ -0,0 +1,3 @@
import { TdCalendarProps } from './type';
declare const props: TdCalendarProps;
export default props;

View File

@ -0,0 +1,50 @@
const props = {
autoClose: {
type: Boolean,
value: true,
},
confirmBtn: {
type: null,
value: '',
},
style: {
type: String,
value: '',
},
firstDayOfWeek: {
type: Number,
value: 0,
},
format: {
type: null,
},
maxDate: {
type: Number,
},
minDate: {
type: Number,
},
title: {
type: String,
},
type: {
type: String,
value: 'single',
},
usePopup: {
type: Boolean,
value: true,
},
value: {
type: null,
value: null,
},
defaultValue: {
type: null,
},
visible: {
type: Boolean,
value: false,
},
};
export default props;

View File

@ -0,0 +1,71 @@
<wxs src="../common/utils.wxs" module="_" />
<import src="../common/template/button.wxml" />
<view
class="{{_.cls(classPrefix, [['popup', usePopup]])}} class {{prefix}}-class"
style="{{_._style([style, customStyle])}}"
>
<view class="{{classPrefix}}__title" tabindex="0">
<slot name="title" />
<text>{{ title || '请选择日期' }}</text>
</view>
<t-icon
wx:if="{{usePopup}}"
name="close"
class="{{classPrefix}}__close-btn"
size="24"
aria-role="button"
aria-label="关闭"
bind:tap="handleClose"
/>
<view aria-hidden class="{{classPrefix}}__days">
<view wx:for="{{days}}" wx:key="index" class="{{classPrefix}}__days-item">{{ item }}</view>
</view>
<scroll-view
class="{{classPrefix}}__months"
scroll-into-view="{{scrollIntoView}}"
scroll-y
enhanced
show-scrollbar="{{false}}"
>
<block wx:for="{{months}}" wx:key="index">
<view class="{{classPrefix}}__month" id="year_{{item.year}}_month_{{item.month}}"
>{{ item.year }} 年 {{ item.month + 1 }} 月</view
>
<view class="{{classPrefix}}__dates">
<view wx:for="{{(item.weekdayOfFirstDay - firstDayOfWeek + 7) % 7}}" wx:key="index" />
<block wx:for="{{item.months}}" wx:for-index="dateIndex" wx:for-item="dateItem" wx:key="dateIndex">
<view
class="{{classPrefix}}__dates-item {{dateItem.className}} {{classPrefix}}__dates-item--{{dateItem.type}}"
data-year="{{item.year}}"
data-month="{{item.month}}"
data-date="{{dateItem}}"
aria-role="button"
aria-label="{{this.getDateLabel(item, dateItem)}}"
aria-disabled="{{dateItem.type === 'disabled'}}"
bind:tap="handleSelect"
>
<view wx:if="{{dateItem.prefix}}" class="{{classPrefix}}__dates-item-prefix">{{ dateItem.prefix }}</view>
{{ dateItem.day }}
<view
wx:if="{{dateItem.suffix}}"
class="{{classPrefix}}__dates-item-suffix {{classPrefix}}__dates-item-suffix--{{dateItem.type}}"
>
{{ dateItem.suffix }}
</view>
</view>
</block>
</view>
</block>
</scroll-view>
<view wx:if="{{innerConfirmBtn != null && usePopup}}" class="{{classPrefix}}__footer">
<slot wx:if="{{innerConfirmBtn === 'slot'}}" name="confirm-btn" />
<block wx:elif="{{innerConfirmBtn}}">
<!-- <t-button block theme="primary" v-bind="confirmBtn" bind:tap="handleConfirm" /> -->
<template
is="button"
data="{{ block: true, theme: 'primary', class: 't-calendar__confirm-btn', ...innerConfirmBtn }}"
/>
</block>
</view>
</view>

View File

@ -0,0 +1,65 @@
import { ButtonProps } from '../button/index';
export interface TdCalendarProps {
autoClose?: {
type: BooleanConstructor;
value?: boolean;
};
confirmBtn?: {
type: null;
value?: string | ButtonProps | null;
};
style?: {
type: StringConstructor;
value?: string;
};
firstDayOfWeek?: {
type: NumberConstructor;
value?: number;
};
format?: {
type: undefined;
value?: CalendarFormatType;
};
maxDate?: {
type: NumberConstructor;
value?: number;
};
minDate?: {
type: NumberConstructor;
value?: number;
};
title?: {
type: StringConstructor;
value?: string;
};
type?: {
type: StringConstructor;
value?: 'single' | 'multiple' | 'range';
};
usePopup?: {
type: BooleanConstructor;
value?: boolean;
};
value?: {
type: null;
value?: number | number[];
};
defaultValue?: {
type: null;
value?: number | number[];
};
visible?: {
type: BooleanConstructor;
value?: boolean;
};
}
export declare type CalendarFormatType = (day: TDate) => TDate;
export declare type TDateType = 'selected' | 'disabled' | 'start' | 'centre' | 'end' | '';
export interface TDate {
date: Date;
day: number;
type: TDateType;
className?: string;
prefix?: string;
suffix?: string;
}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,40 @@
:: BASE_DOC ::
## API
### Cascader Props
name | type | default | description | required
-- | -- | -- | -- | --
close-btn | Boolean / Slot | true | \- | N
keys | Object | - | Typescript`KeysType` | N
options | Array | [] | Typescript`Array<CascaderOption>` | N
sub-titles | Array | [] | Typescript`Array<string>` | N
theme | String | step | optionsstep/tab | N
title | String / Slot | - | \- | N
value | String / Number | null | \- | N
default-value | String / Number | undefined | uncontrolled property | N
visible | Boolean | false | \- | N
### Cascader Events
name | params | description
-- | -- | --
change | `(value: string \| number, selectedOptions: string[])` | `1.0.1`
close | `(trigger: TriggerSource)` | `1.0.1`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/cascader/type.ts)。<br/>`type TriggerSource = 'overlay' \| 'close-btn' \| 'finish'`<br/>
pick | `(value: string \| number, index: number)` | `1.0.1`
### CSS Variables
The component provides the following CSS variables, which can be used to customize styles.
Name | Default Value | Description
-- | -- | --
--td-cascader-active-color | @brand-color | -
--td-cascader-border-color | @border-color | -
--td-cascader-disabled-color | @font-gray-4 | -
--td-cascader-options-height | 640rpx | -
--td-cascader-options-title-color | @font-gray-3 | -
--td-cascader-step-arrow-color | @font-gray-3 | -
--td-cascader-step-dot-size | 16rpx | -
--td-cascader-step-height | 88rpx | -
--td-cascader-title-color | @font-gray-1 | -
--td-cascder-title-font-size | 36rpx | -

View File

@ -0,0 +1,86 @@
---
title: Cascader 级联选择器
description: 级联选择器适用于有清晰层级结构的数据集合,用户可以通过逐级查看并选择。
spline: form
isComponent: true
---
<div style="background: #ecf2fe; display: flex; align-items: center; line-height: 20px; padding: 14px 24px; border-radius: 3px; color: #555a65">
<svg fill="none" viewBox="0 0 16 16" width="16px" height="16px" style="margin-right: 5px">
<path fill="#0052d9" d="M8 15A7 7 0 108 1a7 7 0 000 14zM7.4 4h1.2v1.2H7.4V4zm.1 2.5h1V12h-1V6.5z" fillOpacity="0.9"></path>
</svg>
该组件于 0.23.0 版本上线,请留意版本。
</div>
## 引入
全局引入,在 miniprogram 根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
```json
"usingComponents": {
"t-cascader": "tdesign-miniprogram/cascader/cascader"
}
```
## 代码演示
### 基础用法
{{ base }}
### 选项卡风格
{{ theme-tab }}
### 进阶
#### 带初始值
{{ with-value }}
#### 自定义 keys
{{ keys }}
#### 使用次级标题
{{ with-title }}
## API
### Cascader Props
名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
close-btn | Boolean / Slot | true | 关闭按钮 | N
keys | Object | - | 用来定义 value / label 在 `options` 中对应的字段别名。TS 类型:`KeysType` | N
options | Array | [] | 可选项数据源。TS 类型:`Array<CascaderOption>` | N
sub-titles | Array | [] | 每级展示的次标题。TS 类型:`Array<string>` | N
theme | String | step | 展示风格。可选项step/tab | N
title | String / Slot | - | 标题 | N
value | String / Number | null | 选项值 | N
default-value | String / Number | undefined | 选项值。非受控属性 | N
visible | Boolean | false | 是否展示 | N
### Cascader Events
名称 | 参数 | 描述
-- | -- | --
change | `(value: string \| number, selectedOptions: string[])` | `1.0.1`。值发生变更时触发
close | `(trigger: TriggerSource)` | `1.0.1`。关闭时触发。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/src/cascader/type.ts)。<br/>`type TriggerSource = 'overlay' \| 'close-btn' \| 'finish'`<br/>
pick | `(value: string \| number, index: number)` | `1.0.1`。选择后触发
### CSS 变量
组件提供了下列 CSS 变量,可用于自定义样式。
名称 | 默认值 | 描述
-- | -- | --
--td-cascader-active-color | @brand-color | -
--td-cascader-border-color | @border-color | -
--td-cascader-disabled-color | @font-gray-4 | -
--td-cascader-options-height | 640rpx | -
--td-cascader-options-title-color | @font-gray-3 | -
--td-cascader-step-arrow-color | @font-gray-3 | -
--td-cascader-step-dot-size | 16rpx | -
--td-cascader-step-height | 88rpx | -
--td-cascader-title-color | @font-gray-1 | -
--td-cascder-title-font-size | 36rpx | -

View File

@ -0,0 +1,40 @@
/// <reference types="miniprogram-api-typings" />
import { SuperComponent } from '../common/src/index';
import { TdCascaderProps } from './type';
export interface CascaderProps extends TdCascaderProps {
}
export default class Cascader extends SuperComponent {
externalClasses: string[];
options: WechatMiniprogram.Component.ComponentOptions;
properties: TdCascaderProps<import("../common/common").TreeOptionData>;
controlledProps: {
key: string;
event: string;
}[];
data: {
prefix: string;
name: string;
stepIndex: number;
selectedIndexes: any[];
selectedValue: any[];
defaultOptionLabel: string;
scrollTopList: any[];
steps: string[];
};
observers: {
visible(v: any): void;
'selectedIndexes, options'(): void;
stepIndex(): Promise<void>;
};
methods: {
initWithValue(): void;
getIndexesByValue(options: import("../common/common").TreeOptionData[], value: any): any[];
updateScrollTop(): void;
hide(trigger: any): void;
onVisibleChange(): void;
onClose(): void;
onStepClick(e: any): void;
onTabChange(e: any): void;
handleSelect(e: any): void;
};
}

View File

@ -0,0 +1,186 @@
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;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { SuperComponent, wxComponent } from '../common/src/index';
import config from '../common/config';
import props from './props';
import { getRect } from '../common/utils';
const { prefix } = config;
const name = `${prefix}-cascader`;
const defaultOptionLabel = '选择选项';
let Cascader = class Cascader extends SuperComponent {
constructor() {
super(...arguments);
this.externalClasses = [`${prefix}-class`];
this.options = {
multipleSlots: true,
};
this.properties = props;
this.controlledProps = [
{
key: 'value',
event: 'change',
},
];
this.data = {
prefix,
name,
stepIndex: 0,
selectedIndexes: [],
selectedValue: [],
defaultOptionLabel,
scrollTopList: [],
steps: [defaultOptionLabel],
};
this.observers = {
visible(v) {
if (v) {
const $tabs = this.selectComponent('#tabs');
$tabs === null || $tabs === void 0 ? void 0 : $tabs.setTrack();
this.updateScrollTop();
this.initWithValue();
}
},
'selectedIndexes, options'() {
var _a, _b, _c, _d;
const { options, selectedIndexes, keys } = this.data;
const selectedValue = [];
const steps = [];
const items = [options];
if (options.length > 0) {
for (let i = 0, size = selectedIndexes.length; i < size; i += 1) {
const index = selectedIndexes[i];
const next = items[i][index];
selectedValue.push(next[(_a = keys === null || keys === void 0 ? void 0 : keys.value) !== null && _a !== void 0 ? _a : 'value']);
steps.push(next[(_b = keys === null || keys === void 0 ? void 0 : keys.label) !== null && _b !== void 0 ? _b : 'label']);
if (next[(_c = keys === null || keys === void 0 ? void 0 : keys.children) !== null && _c !== void 0 ? _c : 'children']) {
items.push(next[(_d = keys === null || keys === void 0 ? void 0 : keys.children) !== null && _d !== void 0 ? _d : 'children']);
}
}
}
if (steps.length < items.length) {
steps.push(defaultOptionLabel);
}
this.setData({
steps,
items,
selectedValue,
stepIndex: items.length - 1,
});
},
stepIndex() {
return __awaiter(this, void 0, void 0, function* () {
const { visible } = this.data;
if (visible) {
this.updateScrollTop();
}
});
},
};
this.methods = {
initWithValue() {
if (this.data.value != null && this.data.value !== '') {
const selectedIndexes = this.getIndexesByValue(this.data.options, this.data.value);
if (selectedIndexes) {
this.setData({ selectedIndexes });
}
}
else {
this.setData({ selectedIndexes: [] });
}
},
getIndexesByValue(options, value) {
var _a, _b, _c;
const { keys } = this.data;
for (let i = 0, size = options.length; i < size; i += 1) {
const opt = options[i];
if (opt[(_a = keys === null || keys === void 0 ? void 0 : keys.value) !== null && _a !== void 0 ? _a : 'value'] === value) {
return [i];
}
if (opt[(_b = keys === null || keys === void 0 ? void 0 : keys.children) !== null && _b !== void 0 ? _b : 'children']) {
const res = this.getIndexesByValue(opt[(_c = keys === null || keys === void 0 ? void 0 : keys.children) !== null && _c !== void 0 ? _c : 'children'], value);
if (res) {
return [i, ...res];
}
}
}
},
updateScrollTop() {
const { visible, items, selectedIndexes, stepIndex } = this.data;
if (visible) {
getRect(this, '.cascader-radio-group-0').then((rect) => {
var _a;
const eachRadioHeight = rect.height / ((_a = items[0]) === null || _a === void 0 ? void 0 : _a.length);
this.setData({
[`scrollTopList[${stepIndex}]`]: eachRadioHeight * selectedIndexes[stepIndex],
});
});
}
},
hide(trigger) {
this.setData({ visible: false });
this.triggerEvent('close', { trigger: trigger });
},
onVisibleChange() {
this.hide('overlay');
},
onClose() {
this.hide('close-btn');
},
onStepClick(e) {
const { index } = e.currentTarget.dataset;
this.setData({ stepIndex: index });
},
onTabChange(e) {
const { value } = e.detail;
this.setData({
stepIndex: value,
});
},
handleSelect(e) {
var _a, _b, _c;
const { level } = e.target.dataset;
const { value } = e.detail;
const { selectedIndexes, items, keys } = this.data;
const index = items[level].findIndex((item) => { var _a; return item[(_a = keys === null || keys === void 0 ? void 0 : keys.value) !== null && _a !== void 0 ? _a : 'value'] === value; });
const item = items[level][index];
if (item.disabled) {
return;
}
selectedIndexes[level] = index;
selectedIndexes.length = level + 1;
this.triggerEvent('pick', { value: item[(_a = keys === null || keys === void 0 ? void 0 : keys.value) !== null && _a !== void 0 ? _a : 'value'], index, level });
if ((_c = item === null || item === void 0 ? void 0 : item[(_b = keys === null || keys === void 0 ? void 0 : keys.children) !== null && _b !== void 0 ? _b : 'children']) === null || _c === void 0 ? void 0 : _c.length) {
this.setData({ selectedIndexes });
}
else {
this.setData({ selectedIndexes }, () => {
var _a;
const { items } = this.data;
this._trigger('change', {
value: item[(_a = keys === null || keys === void 0 ? void 0 : keys.value) !== null && _a !== void 0 ? _a : 'value'],
selectedOptions: items.map((item, index) => item[selectedIndexes[index]]),
});
});
this.hide('finish');
}
},
};
}
};
Cascader = __decorate([
wxComponent()
], Cascader);
export default Cascader;

View File

@ -0,0 +1,10 @@
{
"component": true,
"usingComponents": {
"t-icon": "../icon/icon",
"t-popup": "../popup/popup",
"t-tabs": "../tabs/tabs",
"t-tab-panel": "../tab-panel/tab-panel",
"t-radio-group": "../radio-group/radio-group"
}
}

View File

@ -0,0 +1,64 @@
<wxs src="../common/utils.wxs" module="_" />
<t-popup class="class" visible="{{visible}}" placement="bottom" bind:visible-change="onVisibleChange">
<view style="{{_._style([style, customStyle])}}" class="{{name}}">
<view class="{{name}}__title">
<slot name="title" />
{{title}}
</view>
<view class="{{name}}__close-btn" bind:tap="onClose">
<slot name="close-btn" />
<t-icon wx:if="{{closeBtn}}" size="24" name="close" />
</view>
<view class="{{name}}__content">
<block wx:if="{{steps && steps.length}}">
<view wx:if="{{theme == 'step'}}" class="{{name}}__steps">
<view wx:for="{{steps}}" wx:key="index" class="{{name}}__step" bind:tap="onStepClick" data-index="{{index}}">
<view
class="{{name}}__step-dot {{name}}__step-dot--{{item !== defaultOptionLabel ? 'active' : ''}} {{name}}__step-dot--{{index === steps.length - 1 ? 'last' : ''}}"
></view>
<view class="{{name}}__step-label {{name}}__step-label--{{index === stepIndex ? 'active' : ''}}">
{{ item }}
</view>
<t-icon name="chevron-right" size="22" t-class="{{name}}__step-arrow" />
</view>
</view>
<block wx:if="{{theme == 'tab'}}">
<t-tabs id="tabs" value="{{stepIndex}}" bind:change="onTabChange" space-evenly="{{false}}">
<t-tab-panel wx:for="{{steps}}" wx:key="index" value="{{index}}" label="{{item}}" />
</t-tabs>
</block>
</block>
<view wx:if="{{ subTitles && subTitles[stepIndex] }}" class="{{name}}__options-title"
>{{subTitles[stepIndex]}}</view
>
<view
class="{{name}}__options-container"
style="width: {{items.length + 1}}00vw; transform: translateX(-{{stepIndex}}00vw)"
>
<scroll-view
wx:for="{{items}}"
wx:for-item="options"
wx:key="index"
class="{{name}}__options"
scroll-y
scroll-top="{{scrollTopList[index]}}"
>
<view class="cascader-radio-group-{{index}}">
<t-radio-group
value="{{selectedValue[index]}}"
keys="{{keys}}"
options="{{options}}"
bind:change="handleSelect"
data-level="{{index}}"
placement="right"
icon="line"
borderless
>
</t-radio-group>
</view>
</scroll-view>
</view>
</view>
</view>
</t-popup>

View File

@ -0,0 +1,136 @@
.t-float-left {
float: left;
}
.t-float-right {
float: right;
}
@keyframes tdesign-fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.hotspot-expanded.relative {
position: relative;
}
.hotspot-expanded::after {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
transform: scale(1.5);
}
.t-cascader {
display: flex;
flex-direction: column;
background-color: #fff;
color: var(--td-cascader-title-color, var(--td-font-gray-1, rgba(0, 0, 0, 0.9)));
border-radius: 24rpx 24rpx 0 0;
--td-radio-icon-checked-color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
--td-tab-item-active-color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
--td-tab-track-color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-cascader__close-btn {
right: 16px;
top: 12px;
position: absolute;
}
.t-cascader__title {
position: relative;
font-weight: 700;
text-align: center;
line-height: 48px;
font-size: var(--td-cascder-title-font-size, 36rpx);
}
.t-cascader__content {
width: 100%;
flex: 1;
display: flex;
flex-direction: column;
}
.t-cascader__options {
width: 100vw;
height: var(--td-cascader-options-height, 640rpx);
}
.t-cascader__options-title {
margin-top: 40rpx;
color: var(--td-cascader-options-title-color, var(--td-font-gray-3, rgba(0, 0, 0, 0.4)));
font-size: 28rpx;
line-height: 44rpx;
padding-left: 16px;
}
.t-cascader__options-content {
flex: 1;
height: 100%;
overflow: auto;
padding-left: 16px;
}
.t-cascader__options-container {
display: flex;
transition: all ease 0.3s;
}
.t-cascader__step {
display: flex;
align-items: center;
height: var(--td-cascader-step-height, 88rpx);
}
.t-cascader__steps {
padding: 0 32rpx 10rpx;
position: relative;
}
.t-cascader__steps::after {
content: '';
display: block;
position: absolute;
top: unset;
bottom: 0;
left: unset;
right: unset;
background-color: var(--td-cascader-border-color, var(--td-border-color, var(--td-gray-color-3, #e7e7e7)));
}
.t-cascader__steps::after {
height: 1px;
left: 0;
right: 0;
transform: scaleY(0.5);
}
.t-cascader__step-dot {
position: relative;
width: var(--td-cascader-step-dot-size, 16rpx);
height: var(--td-cascader-step-dot-size, 16rpx);
border-radius: 50%;
border: 1px solid var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
box-sizing: border-box;
}
.t-cascader__step-dot:not(.t-cascader__step-dot--last)::after {
content: '';
display: block;
position: absolute;
left: 50%;
top: calc(var(--td-cascader-step-dot-size, 16rpx) + 14rpx);
height: 36rpx;
width: 1px;
background: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
transform: translateX(-50%);
}
.t-cascader__step-dot--active {
background: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
border-color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
}
.t-cascader__step-label {
padding-left: 16px;
font-size: 16px;
}
.t-cascader__step-label--active {
color: var(--td-cascader-active-color, var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
font-weight: 600;
}
.t-cascader__step-arrow {
color: var(--td-cascader-step-arrow-color, var(--td-font-gray-3, rgba(0, 0, 0, 0.4)));
margin-left: auto;
}

Some files were not shown because too many files have changed in this diff Show More