This commit is contained in:
Ling53666
2025-08-18 09:11:51 +08:00
commit 02554225da
2516 changed files with 133155 additions and 0 deletions

View File

@ -0,0 +1 @@
.ant-actionsheet{padding-left:12px;padding-right:12px;padding-bottom:constant(safe-area-inset-bottom);padding-bottom:env(safe-area-inset-bottom)}.ant-actionsheet-title-wrap{text-align:center;position:relative;margin:0 -12px}.ant-actionsheet-title-content{display:inline-block;text-align:left;padding:18px 15px;font-size:15px;color:#999}.ant-actionsheet-title-content::after{content:'';position:absolute;background-color:#eee;display:block;top:auto;right:0;bottom:0;left:0;height:1px;transform:scaleY(.5)}.ant-actionsheet-list{margin:0 -12px}.ant-actionsheet-list-item{color:#333;padding:16px 15px;text-align:center;position:relative;font-size:18px}.ant-actionsheet-list-item::after{content:'';position:absolute;background-color:#eee;display:block;top:auto;right:0;bottom:0;left:0;height:1px;transform:scaleY(.5)}.ant-actionsheet-list-item-title-danger{color:#ff3141;font-weight:700}.ant-actionsheet-list-item-description{color:#999;font-size:14px;line-height:20px;margin-top:4px}.ant-actionsheet-list-item-active{background-color:#eee}.ant-actionsheet-list-item:last-child.ant-actionsheet-list-item:last-child:after{display:none}.ant-actionsheet-list-item-disabled .ant-actionsheet-list-item-content,.ant-actionsheet-list-item-disabled .ant-actionsheet-list-item-icon{opacity:.4}.ant-actionsheet-cancel-gap{height:8px;background:#f5f5f5;margin:0 -12px}.ant-actionsheet-cancel{color:#333;padding:16px 15px;font-size:18px;text-align:center;margin:0 -12px}.ant-actionsheet-cancel:active{background-color:#eee}.ant-actionsheet-icon .ant-actionsheet-title-wrap{text-align:left}.ant-actionsheet-icon .ant-actionsheet-list-item{display:flex;align-items:center}.ant-actionsheet-icon .ant-actionsheet-list-item-icon{height:24px;flex:0 0 24px;margin-right:12px;background-size:contain;background-position:center center;background-repeat:no-repeat}.ant-actionsheet-icon .ant-actionsheet-list-item-content{text-align:left}

View File

@ -0,0 +1,67 @@
<import-sjs
from="./index.sjs"
name="helper"
></import-sjs>
<ant-popup
className="ant-actionsheet-popup"
visible="{{visible}}"
position="bottom"
zIndex="{{zIndex}}"
onClose="onClose"
>
<view
style="{{style}}"
class="ant-actionsheet {{className ? className : ''}} {{helper.isIconMode(actions) ? 'ant-actionsheet-icon' : ''}}"
>
<slot name="title">
<view
a:if="{{title}}"
class="ant-actionsheet-title-wrap"
>
<view class="ant-actionsheet-title-content">{{title}}</view>
</view>
</slot>
<view class="ant-actionsheet-list">
<block
a:for="{{actions}}"
a:for-index="index"
a:for-item="item"
key="{{index}}"
>
<view
class="ant-actionsheet-list-item {{item.disabled ? 'ant-actionsheet-list-item-disabled' : ''}}"
hoverClass="{{item.disabled ? '' : 'ant-actionsheet-list-item-active'}}"
onTap="onAction"
data-index="{{index}}"
data-item="{{item}}"
>
<view
a:if="{{helper.isIconMode(actions)}}"
class="ant-actionsheet-list-item-icon"
style="background-image: url('{{item.icon}}')"
></view>
<view class="ant-actionsheet-list-item-content">
<view class="ant-actionsheet-list-item-title {{item.danger ? 'ant-actionsheet-list-item-title-danger' : ''}}">
{{item.text}}
</view>
<view
a:if="{{item.description}}"
class="ant-actionsheet-list-item-description"
>
{{item.description}}
</view>
</view>
</view>
</block>
</view>
<view class="ant-actionsheet-cancel-gap"></view>
<slot name="cancelText">
<view
class="ant-actionsheet-cancel"
onTap="onClose"
>
{{cancelText}}
</view>
</slot>
</view>
</ant-popup>

View File

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

View File

@ -0,0 +1,14 @@
import { Component, triggerEventOnly, triggerEventValues } from '../_util/simply';
import { ActionSheetDefaultProps } from './props';
Component(ActionSheetDefaultProps, {
onAction: function (e) {
var _a = e.currentTarget.dataset, item = _a.item, index = _a.index;
if (item === null || item === void 0 ? void 0 : item.disabled)
return;
triggerEventOnly(this, 'close', e);
triggerEventValues(this, 'action', [item, index], e);
},
onClose: function (e) {
triggerEventOnly(this, 'close', e);
}
});

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"ant-popup": "../Popup/index"
}
}

View File

@ -0,0 +1,8 @@
function isIconMode(actions) {
return actions.some(function (action) {
return !!action.icon;
});
}
export default {
isIconMode: isIconMode
};

View File

@ -0,0 +1,43 @@
import { IBaseProps } from '../_util/base';
export interface IActionItem {
text: string;
icon: string;
description?: string;
danger?: boolean;
disabled?: boolean;
}
/**
* @description 头像,可展示头像以及用户名等简要信息。
*/
export interface IActionSheetProps extends IBaseProps {
/**
* @description 标题
* @default ""
*/
title: string;
/**
* @description 面板选项列表
* @default []
*/
actions: IActionItem[];
/**
* @description 取消按钮文字
* @default []
*/
cancelText: string;
/**
* @description 是否显示
* @default false
*/
visible: boolean;
zIndex: number;
/**
* @description 点击选项时触发,禁用或加载状态下不会触发
*/
onAction: (aciton: IActionItem, index: number, e: any) => void;
/**
* @description 关闭时触发
*/
onClose: (e: any) => void;
}
export declare const ActionSheetDefaultProps: Partial<IActionSheetProps>;

View File

@ -0,0 +1,8 @@
export var ActionSheetDefaultProps = {
title: '',
actions: [],
cancelText: '取消',
visible: false,
// 弹窗层级
zIndex: 998,
};

View File

@ -0,0 +1 @@
.ant-avatar{display:inline-flex;align-items:center}.ant-avatar-image{width:52px;height:52px;border-radius:4px}.ant-avatar-image-x-small{width:40px;height:40px}.ant-avatar-image-small{width:44px;height:44px}.ant-avatar-image-medium{width:52px;height:52px}.ant-avatar-image-large{width:60px;height:60px}.ant-avatar-circle{border-radius:100vh}

View File

@ -0,0 +1,13 @@
<import-sjs
from="./index.sjs"
name="utils"
></import-sjs>
<view
class="ant-avatar {{className ? className : ''}}"
style="{{style}}"
>
<image
class="ant-avatar-image {{utils.getClass(size)}}"
src="{{src || utils.defaultSrc}}"
></image>
</view>

View File

@ -0,0 +1 @@
import '../_util/assert-component2';

View File

@ -0,0 +1,4 @@
import '../_util/assert-component2';
import { Component } from '../_util/simply';
import { AvatarDefaultProps } from './props';
Component(AvatarDefaultProps);

View File

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

View File

@ -0,0 +1,12 @@
function getClass(size) {
var list = ['x-small', 'small', 'medium', 'large'];
if (list.indexOf(size) >= 0) {
return "ant-avatar-image-".concat(size);
}
return 'ant-avatar-image-medium';
}
var defaultSrc = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTIwcHgiIGhlaWdodD0iMTIwcHgiIHZpZXdCb3g9IjAgMCAxMjAgMTIwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPHRpdGxlPuS/oeaBr+Wxleekujo0MC/lpLTlg49BdmF0YXIv5Y2V5Zu+OjEv5bC65a+4OuWkpzwvdGl0bGU+CiAgICA8ZGVmcz4KICAgICAgICA8cGF0aCBkPSJNOCwwIEwxMTIsMCBDMTE2LjQxODI3OCwtOC4xMTYyNDUwMWUtMTYgMTIwLDMuNTgxNzIyIDEyMCw4IEwxMjAsMTEyIEMxMjAsMTE2LjQxODI3OCAxMTYuNDE4Mjc4LDEyMCAxMTIsMTIwIEw4LDEyMCBDMy41ODE3MjIsMTIwIDUuNDEwODMwMDFlLTE2LDExNi40MTgyNzggMCwxMTIgTDAsOCBDLTUuNDEwODMwMDFlLTE2LDMuNTgxNzIyIDMuNTgxNzIyLDguMTE2MjQ1MDFlLTE2IDgsMCBaIiBpZD0icGF0aC0xIj48L3BhdGg+CiAgICA8L2RlZnM+CiAgICA8ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyBpZD0i5aS05YOPIj4KICAgICAgICAgICAgPG1hc2sgaWQ9Im1hc2stMiIgZmlsbD0id2hpdGUiPgogICAgICAgICAgICAgICAgPHVzZSB4bGluazpocmVmPSIjcGF0aC0xIj48L3VzZT4KICAgICAgICAgICAgPC9tYXNrPgogICAgICAgICAgICA8dXNlIGlkPSJNYXNrIiBmaWxsPSIjRUVFRUVFIiBmaWxsLXJ1bGU9Im5vbnplcm8iIHhsaW5rOmhyZWY9IiNwYXRoLTEiPjwvdXNlPgogICAgICAgICAgICA8cGF0aCBkPSJNNjAuNzc4Mjk5MywyMS44MTgxODE4IEw1OS4yMjE2NTIzLDIxLjgxODE4MTggTDU4LjU3ODQzNTksMjEuODI5OTY0MSBMNTguNTc4NDM1NywyMS44Mjk5NjQxIEM0OS44MDIxNTI3LDIyLjE3NDgzNiA0Mi44NjQ3OTEzLDI5LjQxMDY0NyA0Mi44NjUyMDQzLDM4LjIxOTE2MzMgTDQyLjg2NTIwNDMsNDcuNDI0MDc1MSBMNDIuODg1NzYzNyw0OC4yMzQxMDc0IEw0Mi44ODU3NjI3LDQ4LjIzNDA4NTYgQzQzLjA5MDQ4MjMsNTIuNTUwMjgwNCA0NC45MjExODc0LDU2LjYyNzYzNTUgNDguMDA3OTc5LDU5LjY0MjI3OTQgTDUyLjExMTA1ODEsNjMuNjUxMjA1MiBMNTIuMzc1MzkzNiw2My45NDI4MTY3IEM1Mi44NzQ2OTQ0LDY0LjU1MjU0OTcgNTMuMTQ3ODQxMSw2NS4zMTgzOTg0IDUzLjE0Nzg0MTEsNjYuMTEzNzA2NiBMNTMuMTQ3ODQxMSw2Ni42NzMzNjQ1IEw1My4xMjE0MDc2LDY3LjA3NjkwODEgTDUzLjEyMTQwNzYsNjcuMDc2OTA3OSBDNTIuOTg3ODc0NSw2OC4xNTYyNzIxIDUyLjMzMDE4ODEsNjkuMDk5MzI3MyA1MS4zNjUwNDk2LDY5LjU5NTM3MDUgTDI1LjU1MTE3Myw4Mi44MzI3NjM1IEwyNS4xMDQ3MzkzLDgzLjA4MzEzNjUgTDI1LjEwNDczOTUsODMuMDgzMTM2NCBDMjMuMDY0NzcxNSw4NC4zMjk4MTQgMjEuODE5NDYyMiw4Ni41NTIwMDEgMjEuODE4MTgxOCw4OC45NDc3ODUyIEwyMS44MTgxODE4LDkwLjA5NjU1NzcgTDIxLjgzNTgwNDIsOTAuNTM4MzkzMiBDMjIuMDU5MDIwNCw5My4yODk1NTEzIDI0LjM1NTgwMjcsOTUuNDU0NTQ1NSAyNy4xNTc3NTksOTUuNDU0NTQ1NSBMOTIuODQyMjQxLDk1LjQ1NDU0NTUgTDkyLjg0MjI0MSw5NS40NTQ1NDU1IEM5NS43OTAwNjM3LDk1LjQ1NDU0NTUgOTguMTgwMTkzNiw5My4wNTg4MDI3IDk4LjE4MTgxODIsOTAuMTAyNDM5NiBMOTguMTgxODE4Miw4OC45NTM2NjcyIEM5OC4xODE4MTgyLDg2LjM3MDQwNjYgOTYuNzQyNjYyOCw4NC4wMDUxMDkxIDk0LjQ0ODgwODgsODIuODMyNzY3NSBMNjguNjM0OTMyMyw2OS41OTUzNzQ1IEw2OC42MzQ5MzIsNjkuNTk1Mzc0NCBDNjcuNTM5NzExNSw2OS4wMzM5NjU3IDY2Ljg1MDk3MDIsNjcuOTAzOTcyNyA2Ni44NTIxNDA0LDY2LjY3MDQyMyBMNjYuODUyMTQwNCw2Ni4xMTA3NjUxIEM2Ni44NTIxNDA0LDY1LjE4NTg1NTYgNjcuMjI4MDg0Nyw2NC4yOTkyMzk0IDY3Ljg4ODkyMzUsNjMuNjUxMjE4NSBMNzEuOTkyMDAyNSw1OS42NDIyOTI3IEw3MS45OTIwMDI5LDU5LjY0MjI5MjQgQzc1LjI3ODYwMTksNTYuNDMxNjgwNiA3Ny4xMzIxODU3LDUyLjAyNTQyMDQgNzcuMTMxODU1Myw0Ny40MjQwNjIyIEw3Ny4xMzE4NTUzLDM4LjIxOTE1MDQgTDc3LjEzMTg1NTMsMzguMjE5MTUxIEM3Ny4xMzE4NTUzLDI5LjE2MTE2MzMgNjkuODEwMTE5OCwyMS44MTgxODE4IDYwLjc3ODI5ODcsMjEuODE4MTgxOCBMNjAuNzc4Mjk5MywyMS44MTgxODE4IFoiIGlkPSLlvaLnirYiIGZpbGw9IiNDQ0NDQ0MiIGZpbGwtcnVsZT0ibm9uemVybyIgbWFzaz0idXJsKCNtYXNrLTIpIj48L3BhdGg+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=';
export default {
getClass: getClass,
defaultSrc: defaultSrc
};

View File

@ -0,0 +1,16 @@
import { IBaseProps } from '../_util/base';
/**
* @description 头像,可展示头像以及用户名等简要信息。
*/
export interface IAvatarProps extends IBaseProps {
/**
* @description 尺寸x-small(80*80) small(88*88) medium(104*104) large(120*120)
* @default "medium"
*/
size: 'x-small' | 'small' | 'medium' | 'large';
/**
* @description 头像地址,默认为灰色的内置图片
*/
src: string;
}
export declare const AvatarDefaultProps: Partial<IAvatarProps>;

View File

@ -0,0 +1,4 @@
export var AvatarDefaultProps = {
size: 'medium',
src: '',
};

View File

@ -0,0 +1 @@
.ant-badge{display:inline-block;position:relative}.ant-badge-content{position:absolute;display:flex;height:14px;align-self:center;align-items:center;font-size:9px;padding:2px 4px;box-sizing:border-box;word-break:keep-all;justify-content:center;top:0;left:100%;transform:translate(-50%,-50%)}.ant-badge-content-stroke{border:1px solid #fff}.ant-badge-content-text{padding-left:2px}.ant-badge-content-text:empty{display:none}.ant-badge-icon-container:empty~.ant-badge-content-text{padding-left:0}.ant-badge-content .ant-icon{font-size:9px;color:#fff}.ant-badge-content-not-dot{min-width:14px;height:14px;border-radius:14px;display:flex;background-color:#ff3141}.ant-badge-dot{width:10px;height:10px;border-radius:50%;background-color:#ff3141}.ant-badge-dot-stroke{border:1px solid #fff}.ant-badge-bubble,.ant-badge-number,.ant-badge-text{color:#fff}

View File

@ -0,0 +1,56 @@
<import-sjs
from="./index.sjs"
name="_sjs"
></import-sjs>
<view
class="ant-badge {{className || ''}}"
style="{{style}}"
>
<view class="ant-badge-body">
<slot></slot>
</view>
<view
a:if="{{type === 'dot'}}"
class="ant-badge-content"
style="{{_sjs.setPositionStyle(position, offsetX, offsetY)}}"
>
<view
class="ant-badge-dot {{stroke ? 'ant-badge-dot-stroke' : ''}}"
style="{{bgColor ? 'background-color: ' + bgColor + ';' : ''}}"
></view>
</view>
<view
a:else
class="ant-badge-content ant-badge-content-not-dot {{type === 'bubble' ? 'ant-badge-content-' + position + '-bubble' : ''}} {{stroke ? 'ant-badge-content-stroke' : ''}}"
style="{{bgColor ? 'background-color: ' + bgColor + ';' : ''}} {{_sjs.setBubbleStyle(type, position)}};{{_sjs.setPositionStyle(position, offsetX, offsetY)}}"
>
<view class="ant-badge-icon-container"></view>
<view class="ant-badge-content-text">
<slot name="text">
<block a:if="{{text}}">
<view
a:if="{{type === 'number'}}"
class="ant-badge-number"
>
<!--display: inline-->
<text a:if="{{_sjs.getOverCount(text)}}">99+</text>
<!--display: inline-->
<text a:else>{{text}}</text>
</view>
<view
a:if="{{type === 'text'}}"
class="ant-badge-text"
>
{{text}}
</view>
<view
a:if="{{type === 'bubble'}}"
class="ant-badge-bubble"
>
{{text}}
</view>
</block>
</slot>
</view>
</view>
</view>

View File

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

View File

@ -0,0 +1,3 @@
import { Component } from '../_util/simply';
import { BadgeFunctionalProps } from './props';
Component(BadgeFunctionalProps);

View File

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

View File

@ -0,0 +1,54 @@
function setPositionStyle(position) {
var offsetX = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-50%';
var offsetY = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '-50%';
var transformStyle = "transform: translate(calc(".concat(offsetX, "), calc(").concat(offsetY, "));");
switch (position) {
case 'top-left':
return "top: 0; left: 0; ".concat(transformStyle);
case 'top-center':
return "top: 0; left: 50%; ".concat(transformStyle);
case 'top-right':
return "top: 0; left: 100%; ".concat(transformStyle);
case 'left':
return "top: 50%; left: 0; ".concat(transformStyle);
case 'right':
return "top: 50%; left: 100%; ".concat(transformStyle);
case 'bottom-left':
return "top: 100%; left: 0; ".concat(transformStyle);
case 'bottom-center':
return "top: 100%; left: 50%; ".concat(transformStyle);
case 'bottom-right':
return "top: 100%; left: 100%; ".concat(transformStyle);
default:
return "top: 0; left: 0; ".concat(transformStyle);
}
}
function setBubbleStyle(type, position) {
if (type !== 'bubble') return '';
switch (position) {
case 'top-left':
return 'border-bottom-right-radius: 0;';
case 'top-right':
return 'border-bottom-left-radius: 0;';
case 'bottom-left':
return 'border-top-right-radius: 0;';
case 'bottom-right':
return 'border-top-left-radius: 0;';
default:
return '';
}
}
function getOverCount(text) {
var overCount = false;
if (typeof text === 'number') {
if (text >= 100) {
overCount = true;
}
}
return overCount;
}
export default {
setPositionStyle: setPositionStyle,
setBubbleStyle: setBubbleStyle,
getOverCount: getOverCount
};

View File

@ -0,0 +1,41 @@
import { IBaseProps } from '../_util/base';
/**
* @description 徽标,红点、数字或文字。用于告诉用户待处理的事物或更新数。
*/
export interface IBadgeProps extends IBaseProps {
/**
* @description badge 类型
* @default dot
*/
type: 'dot' | 'number' | 'text' | 'bubble';
/**
* @description 红点内容,为空时表示只显示红点;可以是数字,也可以是文字;如果是数字,超过 99 会自动变成 ...
*/
text: string | number;
/**
* @description 相对于 children 所在访问left-top(左上角) top-right(右上角)
* @default "top-right"
*/
position: 'top-left' | 'top-center' | 'top-right' | 'left' | 'right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
/**
* @description 水平方向偏移量(字符串类型,需要带上像素单位)
* @default "-50%"
*/
offsetX: string;
/**
* @description 垂直方向偏移量(字符串类型,需要带上像素单位)
* @default "-50%"
*/
offsetY: number | string;
/**
* @description 是否有描边
* @default false
*/
stroke: boolean;
/**
* @description 背景色
*/
bgColor: string;
}
export declare const BadgeDefaultProps: Partial<IBadgeProps>;
export declare const BadgeFunctionalProps: Partial<IBadgeProps>;

View File

@ -0,0 +1,15 @@
export var BadgeDefaultProps = {
position: 'top-right',
stroke: false,
type: 'dot',
bgColor: '',
};
export var BadgeFunctionalProps = {
type: 'dot',
text: null,
position: 'top-right',
offsetX: null,
offsetY: null,
stroke: false,
bgColor: '',
};

View File

@ -0,0 +1 @@
.ant-button{position:relative;display:flex;flex-direction:column;justify-content:center;align-items:center;height:auto;line-height:normal;padding:12px;border-radius:4px;border:0 none;box-sizing:border-box;font-size:18px;z-index:2}.ant-button-large{font-size:18px;padding:12px 12px 12px 12px}.ant-button-medium{font-size:17px;padding:8px 12px 8px 12px}.ant-button-small{font-size:15px;padding:4px 12px 4px 12px}.ant-button-primary{color:#fff;background-color:#1677ff;box-shadow:inset 0 0 0 1px #1677ff}.ant-button-default{color:#1677ff;background-color:#fff;box-shadow:inset 0 0 0 1px #1677ff}.ant-button-text{color:#1677ff;background-color:transparent;box-shadow:none}.ant-button-primary-danger{color:#fff;background-color:#ff3141;box-shadow:inset 0 0 0 1px #ff3141}.ant-button-default-danger{color:#ff3141;background-color:#fff;box-shadow:inset 0 0 0 1px #ff3141}.ant-button-text-danger{color:#ff3141;background-color:transparent;box-shadow:none}.ant-button-text-active{background-color:rgba(255,255,255,.92)}.ant-button-active{filter:brightness(.92)}.ant-button-disabled{opacity:.4}.ant-button-wrap{display:flex;flex-direction:row;align-items:center;justify-content:center}.ant-button-content-text-margin{margin-left:8px}.ant-button-content-text:empty{margin-left:0;width:0;opacity:0}.ant-button-content-text:empty::after{content:'\00a0'}.ant-button-content-subtext{font-size:12px;opacity:.6}.ant-button-content-loading-container{display:flex;justify-content:center;align-items:center;width:33px;height:16px;margin-left:8px}.ant-button-content-loading{position:relative}.ant-button-inline{display:inline-block;border-radius:4px}.ant-button-inline .ant-button-content-loading-container{width:16px;height:16px}.ant-button-inline .ant-button-content-loading{transform:scale(.5)}

View File

@ -0,0 +1,46 @@
<import-sjs
from="./index.sjs"
name="utils"
></import-sjs>
<button
formType="{{formType}}"
hoverClass="{{utils.getHoverClass(loading, type, activeClassName)}}"
scope="{{scope}}"
onTap="{{onTap ? 'onTap' : ''}}"
onGetAuthorize="onGetAuthorize"
onFollowLifestyle="onFollowLifestyle"
onError="onError"
onGetUserInfo="onGetUserInfo"
onGetPhoneNumber="onGetPhoneNumber"
catchTap="{{catchTap ? 'catchTap' : ''}}"
publicId="{{publicId}}"
openType="{{openType}}"
class="ant-button {{inline ? 'ant-button-inline ' + utils.getClass(size) : ''}} {{'ant-button-' + type + (danger ? '-danger' : '')}} {{disabled || loading ? 'ant-button-disabled' : ''}} {{className ? className : ''}}"
style="{{style}}"
>
<view class="ant-button-wrap">
<ant-icon
a:if="{{!!icon}}"
type="{{icon}}"
></ant-icon>
<view class="ant-button-content-text {{icon ? 'ant-button-content-text-margin' : ''}}">
<slot></slot>
<view
a:if="{{!inline && subText}}"
class="ant-button-content-subtext"
>
{{subText}}
</view>
</view>
<view
a:if="{{loading}}"
class="ant-button-content-loading-container"
>
<loading
type="mini"
color="currentColor"
className="ant-button-content-loading"
></loading>
</view>
</view>
</button>

View File

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

View File

@ -0,0 +1,55 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { ButtonDefaultProps } from './props';
import fmtEvent from '../_util/fmtEvent';
Component({
props: ButtonDefaultProps,
methods: {
onTap: function (e) {
var _a = this.props, onTap = _a.onTap, disabled = _a.disabled, loading = _a.loading, onDisabledTap = _a.onDisabledTap;
if (disabled && onDisabledTap) {
var event_1 = fmtEvent(this.props, e);
onDisabledTap(event_1);
}
if (onTap && !disabled && !loading) {
var event_2 = fmtEvent(this.props, e);
return onTap(event_2);
}
},
catchTap: function (e) {
var _a = this.props, catchTap = _a.catchTap, disabled = _a.disabled, loading = _a.loading, onDisabledTap = _a.onDisabledTap;
if (disabled && onDisabledTap) {
var event_3 = fmtEvent(this.props, e);
onDisabledTap(event_3);
}
if (catchTap && !disabled && !loading) {
var event_4 = fmtEvent(this.props, e);
return catchTap(event_4);
}
},
onGetAuthorize: function (e) {
if (this.props.onGetAuthorize) {
this.props.onGetAuthorize(fmtEvent(this.props, e));
}
},
onFollowLifestyle: function (e) {
if (this.props.onFollowLifestyle) {
this.props.onFollowLifestyle(fmtEvent(this.props, e));
}
},
onError: function (e) {
if (this.props.onError) {
this.props.onError(fmtEvent(this.props, e));
}
},
onGetUserInfo: function (e) {
if (this.props.onGetUserInfo) {
this.props.onGetUserInfo(fmtEvent(this.props, e));
}
},
onGetPhoneNumber: function (e) {
if (this.props.onGetPhoneNumber) {
this.props.onGetPhoneNumber(fmtEvent(this.props, e));
}
},
},
});

View File

@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"loading": "../Loading/index",
"ant-icon": "../Icon/index"
}
}

View File

@ -0,0 +1,24 @@
function getClass(size) {
var list = ['small', 'medium', 'large'];
if (list.indexOf(size) >= 0) {
return "ant-button-".concat(size);
}
return 'ant-button-medium';
}
function getHoverClass(loading, type, activeClassName) {
if (loading) {
return '';
}
var className = 'ant-button-active';
if (type === 'text') {
className += ' ant-button-text-active';
}
if (activeClassName) {
className += ' ' + activeClassName;
}
return className;
}
export default {
getClass: getClass,
getHoverClass: getHoverClass
};

View File

@ -0,0 +1,85 @@
import { IBaseProps } from '../_util/base';
/**
* @description 按钮,用户只需单击一下即可执行操作并做出选择。
* 常用于表单提交、界面跳转、模块引导点击。具体用法和小程序框架中 button 保持一致,在 button 基础上做了样式的封装。
* 封装后的按钮可改变按钮形态、增加 loading以及内置了几种不同样式的按钮。
*/
export interface IButtonProps extends IBaseProps {
/**
* @description 按钮类型
* @default default
*/
type?: 'default' | 'primary' | 'text';
/**
* @description 是否禁用
* @default false
*/
disabled?: boolean;
/**
* @description 按下时的类名
*/
activeClassName?: string;
/**
* @description 辅助文字,显示在第二行
*/
subText?: string;
/**
* @description 内联,不撑满父级宽度
* @default false
*/
inline?: boolean;
/**
* @description 内联尺寸
* @default medium
*/
size?: 'small' | 'medium' | 'large';
/**
* @description 按钮左侧图标
*/
icon?: string;
/**
* @description 是否加载中,加载中时不可点击
* @default false
*/
loading?: boolean;
/**
* @description 是否为危险按钮,危险按钮的颜色会变成红色
* @default false
*/
danger?: boolean;
/**
* @description 按钮原生类型,在表单提交时有效
* @default button
*/
formType?: 'button' | 'submit' | 'reset';
/**
* @description 点击回调
*/
onTap?: (event: any) => void;
/**
* @description 点击回调
*/
catchTap?: (event: any) => void;
/**
* @description 禁用时点击回调
*/
onDisabledTap?: (event: any) => void;
/**
* @description 生活号 id必须是当前小程序同主体且已关联的生活号open-type="lifestyle" 时有效。
*/
publicId?: string;
/**
* @description 开放能力。
*/
openType?: string;
/**
* @description 当 openType 为 getAuthorize 时有效。
*/
scope?: string;
onGetAuthorize?: (event: any) => void;
onFollowLifestyle?: (event: any) => void;
onError?: (event: any) => void;
onGetUserInfo?: (event: any) => void;
onGetPhoneNumber?: (event: any) => void;
}
export declare const ButtonDefaultProps: Partial<IButtonProps>;

View File

@ -0,0 +1,5 @@
export var ButtonDefaultProps = {
type: 'default',
formType: 'button',
size: 'medium',
};

View File

@ -0,0 +1,84 @@
function keys(obj) {
if (typeof Object.keys === 'function') {
return Object.keys(obj);
}
}
function getClassName(value, index, showSelectableDatesOnly) {
var isSelected = value.isSelected,
isSelectedBegin = value.isSelectedBegin,
isSelectedEnd = value.isSelectedEnd,
isRowBegin = value.isRowBegin,
isRowEnd = value.isRowEnd,
inThisMonth = value.inThisMonth,
isToday = value.isToday,
disabled = value.disabled,
className = value.className,
isRange = value.isRange;
var classNames = {
disabled: disabled,
today: inThisMonth && isToday,
selected: inThisMonth && isSelected,
'selected-begin': inThisMonth && isSelectedBegin,
'selected-end': inThisMonth && isSelectedEnd,
'selected-row-begin': inThisMonth && isRowBegin && isSelected,
'selected-row-end': inThisMonth && isRowEnd && isSelected,
hidden: !inThisMonth || showSelectableDatesOnly && !isRange,
'row-end': index % 7 === 6
};
var result = "ant-calendar-cell ".concat(className || '');
keys(classNames).forEach(function (key) {
if (classNames[key]) {
result += " ant-calendar-cell-".concat(key);
}
});
return result;
}
function getSpaceClassName(index, items) {
var isNotEnd = index % 7 !== 6;
var nextItem = items[index + 1];
var nextSelected = nextItem && nextItem.isSelected && nextItem.inThisMonth;
var isSelected = items[index].isSelected;
var classNames = {
active: isNotEnd && isSelected && nextSelected
};
var result = 'ant-calendar-cell-space';
keys(classNames).forEach(function (key) {
if (classNames[key]) {
result += " ant-calendar-cell-space-".concat(key);
}
});
return result;
}
function getMarkCellClassName(index, items) {
if (items[index].length - 1 === index) {
return "ant-calendar-mark-cell ant-calendar-mark-cell-last";
}
return 'ant-calendar-mark-cell';
}
function isDisplay(index, items) {
// 找到需要当前月需要展示的日期最大最小索引
var _items_reduce = items.reduce(function (res, item) {
// !item.inThisMonth 被隐藏掉的日期
// !item.isRange 不在传入范围内的日期
if (!(!item.inThisMonth || !item.isRange)) {
if (res.minIndex === null || res.maxIndex === null) {
res.minIndex = item.index;
res.maxIndex = item.index;
}
res.minIndex = Math.min(res.minIndex, item.index);
res.maxIndex = Math.max(res.maxIndex, item.index);
}
return res;
}, {
minIndex: null,
maxIndex: null
});
if (_items_reduce.maxIndex === null || _items_reduce.maxIndex === null) return true;
return index >= Math.floor(_items_reduce.minIndex / 7) * 7 && index < Math.ceil(_items_reduce.maxIndex / 7) * 7;
}
export default {
getSpaceClassName: getSpaceClassName,
getClassName: getClassName,
getMarkCellClassName: getMarkCellClassName,
isDisplay: isDisplay
};

View File

@ -0,0 +1 @@
.ant-calendar{color:#333;position:relative;display:flex;flex-direction:column;height:100%}.ant-calendar-body{flex:1}.ant-calendar-sticky{position:absolute;top:0;left:0;max-height:41px;width:100%;overflow:hidden;top:44px;z-index:1000}.ant-calendar-mark{height:44px;display:flex;flex-direction:row;justify-content:flex-start;align-items:center;box-sizing:border-box;font-size:14px;padding:0 8px}.ant-calendar-mark .ant-calendar-mark-cell{flex:1;text-align:center;width:calc((100% - 6 * 5px)/ 7);margin-right:5px}.ant-calendar-mark .ant-calendar-mark-cell-last{margin-right:0}.ant-calendar-title{color:#333;font-size:18px;height:41px;line-height:41px;padding-left:20px;margin-bottom:4px;background:#f8f8f8}.ant-calendar-cells{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:stretch;padding:0 8px}.ant-calendar-cell-space{width:5px;height:55px}.ant-calendar-cell-space-active{background:rgba(22,119,255,.1)}.ant-calendar-cell{box-sizing:border-box;width:calc((100% - 6 * 5px)/ 7);height:55px;margin-bottom:4px;position:relative}.ant-calendar-cell-container{box-sizing:border-box;padding-top:3.5px;height:100%}.ant-calendar-cell-top{color:#999;text-align:center;font-size:9px;height:12.5px}.ant-calendar-cell-top-text{white-space:nowrap}.ant-calendar-cell-center{text-align:center;height:22.5px;font-size:16px}.ant-calendar-cell-bottom{color:#999;text-align:center;font-size:9px;height:12.5px}.ant-calendar-cell-selected{background:rgba(22,119,255,.1)}.ant-calendar-cell-selected-begin{border-top-left-radius:4px;border-bottom-left-radius:4px;background:rgba(22,119,255,.1)}.ant-calendar-cell-selected-end{border-top-right-radius:4px;border-bottom-right-radius:4px;color:#fff}.ant-calendar-cell-selected-row-end{border-top-right-radius:4px;border-bottom-right-radius:4px}.ant-calendar-cell-selected-row-begin{border-top-left-radius:4px;border-bottom-left-radius:4px}.ant-calendar-cell-selected-begin .ant-calendar-cell-container{background:#1677ff;border-radius:4px;color:#fff}.ant-calendar-cell-selected-end .ant-calendar-cell-container{background:#1677ff;border-radius:4px;color:#fff}.ant-calendar-cell-selected-end .ant-calendar-cell-top{color:#fff}.ant-calendar-cell-selected-begin .ant-calendar-cell-top{color:#fff}.ant-calendar-cell-selected-end .ant-calendar-cell-bottom{color:#fff}.ant-calendar-cell-selected-begin .ant-calendar-cell-bottom{color:#fff}.ant-calendar-cell-disabled{opacity:.4}.ant-calendar-cell-hidden{opacity:0;pointer-events:none}

View File

@ -0,0 +1,110 @@
<import-sjs
from="./helper.sjs"
name="helper"
></import-sjs>
<import-sjs
from="./scroll.sjs"
name="scroll"
></import-sjs>
<view
class="ant-calendar {{className ? className : ''}}"
style="{{style}}"
>
<view class="ant-calendar-mark">
<block
a:for="{{markItems}}"
a:for-index="index"
a:for-item="item"
>
<view class="{{helper.getMarkCellClassName(index, markItems)}}">
<!--display: inline-->
<text>{{item}}</text>
</view>
</block>
</view>
<view
a:if="{{!!elementSize}}"
class="ant-calendar-sticky"
>
<view class="ant-calendar-sticky-title">
<slot name="calendarTitle">
<view class="ant-calendar-title">
{{monthList[headerState].title}}
</view>
</slot>
</view>
</view>
<scroll-view
scrollY="{{true}}"
class="ant-calendar-body"
data-elementsize="{{elementSize}}"
data-monthlist="{{monthList}}"
onScroll="{{scroll.handleScroll}}"
scrollIntoView="{{scrollIntoViewId}}"
scrollWithAnimation
scrollAnimationDuration="{{300}}"
disableLowerScroll="out-of-bounds"
disableUpperScroll="out-of-bounds"
ref="handleRef"
>
<block
a:for="{{monthList}}"
a:for-index="index"
a:for-item="currentMonth"
>
<view
class="ant-calendar-body-container {{currentMonth.className || ''}}"
style="{{currentMonth.style || ''}}"
>
<view class="ant-calendar-title-container">
<slot name="calendarTitle">
<view class="ant-calendar-title">{{currentMonth.title}}</view>
</slot>
</view>
<view class="ant-calendar-cells">
<block
a:for="{{currentMonth.cells}}"
a:for-index="index"
a:for-item="item"
>
<block a:if="{{helper.isDisplay(index, currentMonth.cells)}}">
<view
class="{{helper.getClassName(item, index, showSelectableDatesOnly)}}"
id="id_{{item.time}}"
data-time="{{item}}"
onTap="clickCell"
>
<view class="ant-calendar-cell-container">
<view class="ant-calendar-cell-top">
<!--display: inline-->
<text
a:if="{{item.top}}"
class="ant-calendar-cell-top-text {{item.top.className ? item.top.className : ''}}"
>{{item.top.label}}</text>
</view>
<view class="ant-calendar-cell-center">{{item.date}}</view>
<view class="ant-calendar-cell-bottom">
<slot
name="cell-bottom"
cell="{{item}}"
>
<!--display: inline-->
<text
a:if="{{item.bottom}}"
class="{{item.bottom.className}}"
>{{item.bottom.label}}</text>
</slot>
</view>
</view>
</view>
<view
a:if="{{index % 7 !== 6}}"
class="{{helper.getSpaceClassName(index, currentMonth.cells)}}"
></view>
</block>
</block>
</view>
</view>
</block>
</scroll-view>
</view>

View File

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

View File

@ -0,0 +1,213 @@
import { __assign, __awaiter, __generator, __spreadArray } from "tslib";
import dayjs from 'dayjs';
import equal from 'fast-deep-equal';
import { Component, triggerEvent, getValueFromProps } from '../_util/simply';
import { defaultLocaleText, CalendarDefaultProps, } from './props';
import { getMonthListFromRange, getSelectionModeFromValue, renderCells, getScrollIntoViewId, } from './utils';
import mixinValue from '../mixins/value';
import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect';
Component(CalendarDefaultProps, {
getInstance: function () {
if (this.$id) {
return my;
}
return this;
},
getBoundingClientRect: function (query) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getInstanceBoundingClientRect(this.getInstance(), query)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
},
scrollIntoView: function (value) {
this.updateScrollIntoViewId(getScrollIntoViewId(value));
},
clickCell: function (e) {
var _a, _b;
var time = e.currentTarget.dataset.time;
var clickDate = dayjs(time.time);
if (time.disabled) {
return;
}
var value = this.getValue();
var selectionModeFromValue = getSelectionModeFromValue(value);
var selectionMode = (_b = (_a = getValueFromProps(this, 'selectionMode')) !== null && _a !== void 0 ? _a : selectionModeFromValue) !== null && _b !== void 0 ? _b : 'range';
if (selectionMode === 'range') {
if (Array.isArray(value)) {
if (value.length === 1) {
var current = value[0];
if (dayjs(clickDate.toDate().getTime()).isBefore(dayjs(current))) {
this.updateValue([clickDate.toDate().getTime()]);
}
else {
this.updateValue([value[0], clickDate.toDate().getTime()]);
}
}
else {
this.updateValue([clickDate.toDate().getTime()]);
}
}
else {
this.updateValue([clickDate.toDate().getTime()]);
}
}
else if (selectionMode === 'single') {
this.updateValue(clickDate.toDate().getTime());
}
},
setCurrentMonth: function (e) {
this.setData({ headerState: e.month });
},
measurement: function () {
var elementSize = this.data.elementSize;
// 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0
// 此时需要重新计算
if (!elementSize || elementSize.cellHight === 0) {
this.measurementFn();
}
},
measurementFn: function () {
var _this = this;
Promise.all([
this.getBoundingClientRect('.ant-calendar-body-container'),
this.getBoundingClientRect('.ant-calendar-cells'),
this.getBoundingClientRect('.ant-calendar-title-container'),
])
.then(function (_a) {
var bodyContainer = _a[0], cellContainer = _a[1], Title = _a[2];
// 滚动的时候 top 和 bottom 等尺寸会变
// 所以只能依赖 height 来计算
var paddingHeight = bodyContainer.height - cellContainer.height - Title.height;
var monthTitleHeight = Title.height + paddingHeight;
var cellHight = cellContainer.height / (_this.data.monthList[0].cells.length / 7);
_this.setData({
elementSize: {
monthTitleHeight: monthTitleHeight,
cellHight: cellHight,
paddingHeight: paddingHeight,
},
});
})
.catch(function () {
_this.setData({ elementSize: null });
});
},
// scroll 触发滚动之后需要重置 scrollIntoViewId
updateScrollIntoViewId: function (id) {
var _this = this;
this.setData({ scrollIntoViewId: id });
var timer = setTimeout(function () {
_this.setData({ scrollIntoViewId: '' });
clearTimeout(timer);
});
},
updateValue: function (newValue) {
triggerEvent(this, 'change', newValue);
if (!this.isControlled()) {
this.update(newValue);
}
},
updateData: function () {
var _a = getValueFromProps(this, [
'monthRange',
'localeText',
'weekStartsOn',
'onFormatter',
'onMonthFormatter',
]), monthRange = _a[0], plocaleText = _a[1], pweekStartsOn = _a[2], onFormatter = _a[3], onMonthFormatter = _a[4];
var localeText = Object.assign({}, defaultLocaleText, plocaleText);
var markItems = __spreadArray([], localeText.weekdayNames, true);
var weekStartsOn = pweekStartsOn;
if (weekStartsOn === 'Sunday') {
var item = markItems.pop();
if (item)
markItems.unshift(item);
}
var value = this.getValue();
var start = dayjs(monthRange === null || monthRange === void 0 ? void 0 : monthRange[0]).startOf('d');
var end = dayjs(monthRange === null || monthRange === void 0 ? void 0 : monthRange[1]).startOf('d');
var monthRangeList = getMonthListFromRange(start, end);
var monthList = monthRangeList.map(function (p) {
var cells = renderCells(p, weekStartsOn, value, localeText,
// 如果monthRange传入异常用内置的时间范围
start.isAfter(end) || start.isSame(end)
? [monthRangeList[0], dayjs(monthRangeList[1]).endOf('month')]
: [start, end]);
if (onFormatter && typeof onFormatter === 'function') {
cells = cells.map(function (o) {
var _a;
var time = o.time, top = o.top, bottom = o.bottom, disabled = o.disabled, isSelectedBegin = o.isSelectedBegin, isSelectedEnd = o.isSelectedEnd, isSelected = o.isSelected, className = o.className, isRange = o.isRange;
var newState = (_a = onFormatter({
time: time,
top: top ? __assign({}, top) : undefined,
bottom: bottom ? __assign({}, bottom) : undefined,
disabled: disabled,
isSelectedBegin: isSelectedBegin,
isSelectedEnd: isSelectedEnd,
isSelected: isSelected,
className: className,
isRange: isRange,
}, value)) !== null && _a !== void 0 ? _a : {};
var result = __assign({}, o);
if (typeof newState === 'object') {
// 只允许修改的字段字段
['top', 'bottom', 'disabled', 'className'].forEach(function (key) {
if (key in newState) {
result[key] = newState[key];
}
});
}
return result;
});
}
var month = {
title: p.format(localeText.title),
className: '',
cells: cells,
};
if (onMonthFormatter && typeof onMonthFormatter === 'function') {
month = __assign(__assign({}, month), onMonthFormatter(p));
}
return month;
});
this.setData({ markItems: markItems, monthList: monthList });
},
}, {
elementSize: null,
markItems: [],
monthList: [],
headerState: 0,
scrollIntoViewId: '',
}, [mixinValue()], {
didMount: function () {
this.updateData();
this.measurementFn();
// 初始化默认值时,滚动到选中位置
var _a = getValueFromProps(this, [
'value',
'defaultValue',
]), value = _a[0], defaultValue = _a[1];
if (this.isControlled()) {
this.updateScrollIntoViewId(getScrollIntoViewId(value));
}
else {
defaultValue &&
this.updateScrollIntoViewId(getScrollIntoViewId(defaultValue));
}
},
didUpdate: function (prevProps, prevData) {
if (!this.isEqualValue(prevData)) {
// 滚动到已选的位置
var changedScrollIntoView = getValueFromProps(this, 'changedScrollIntoView');
changedScrollIntoView &&
this.updateScrollIntoViewId(getScrollIntoViewId(this.getValue()));
}
if (!equal(prevProps, this.props) || !this.isEqualValue(prevData)) {
this.updateData();
}
},
});

View File

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

View File

@ -0,0 +1,173 @@
import { IBaseProps } from '../_util/base';
export interface CalendarDate {
year: number;
month: number;
date: number;
}
export declare const defaultLocaleText: {
weekdayNames: string[];
title: string;
today: string;
start: string;
end: string;
startAndEnd: string;
};
export interface LocaleText {
/**
* 星期的名称。从周一到周日
* 默认为 ['一', '二', '三', '四', '五', '六', '日']
*/
weekdayNames: string[];
/**
* 月份标题的格式。 默认为 'YYYY年MM月'
*/
title: string;
/**
* 今日的文案。 默认为 '今日'
*/
today: string;
/**
* 开始的文案。 默认为 '开始'
*/
start: string;
/**
* 结束的文案。 默认为 '结束'
*/
startAndEnd: string;
/**
* 开始/结束的文案。 默认为 '开始/结束'
*/
end: string;
}
export interface CellState {
/**
* 类名
*/
className?: string;
/**
* 是否被禁止
*/
disabled: boolean;
/**
* 日历单元格的顶部内容
*/
top?: {
label: string;
className?: string;
};
/**
* 日历单元格的底部内容
*/
bottom?: {
label: string;
className?: string;
};
/**
* 时间戳
*/
time: number;
/**
* 日期
*/
date: number;
/**
* 是否被选择
*/
isSelected: boolean;
/**
* 是否是选择区间的开始
*/
isSelectedBegin: boolean;
/**
* 是否是选择区间的结束
*/
isSelectedEnd: boolean;
/**
* 是否是每一行的第一个
*/
isRowBegin: boolean;
isRowEnd: boolean;
inThisMonth: boolean;
/**
* 是否在传入范围内
*/
isRange: boolean;
index: number;
}
export type CalendarValue = number | number[];
export type SelectionMode = 'single' | 'range';
export interface ICalendarProps extends IBaseProps {
/**
* 初始值
*/
defaultValue?: CalendarValue;
/**
* 日历选择的日期,受控模式
*/
value?: CalendarValue;
/**
* 设置选择模式,单选或者连续区间, 默认为 'range'
*/
selectionMode?: SelectionMode;
/**
* 月份范围,默认为最近 3 个月
* 格式为时间戳
* @default [本月第一天的时间戳, 3个月后第一天的时间戳]
*/
monthRange?: [number, number];
/**
* 星期栏,以周几作为第一天显示,默认为 'Sunday'
*/
weekStartsOn?: 'Sunday' | 'Monday';
/**
* 国际化文案
*/
localeText?: Partial<LocaleText>;
/**
* 选中值改变后滚动视图
*/
changedScrollIntoView?: boolean;
/**
* 只展示在可选范围内的日期
*/
showSelectableDatesOnly?: boolean;
/**
* 日期变化回调
*/
onChange?: (date: CalendarValue) => void;
/**
* onFormatter 用于设置单元格的自定义数据
* @param cell 原始数据
* @param currentValue 当前的 value
* @returns 返回新的数据
*/
onFormatter?: (cell: Pick<CellState, 'className' | 'disabled' | 'top' | 'bottom' | 'time' | 'isSelectedBegin' | 'isSelectedEnd' | 'isSelected'>, currentValue: CalendarValue) => Pick<CellState, 'disabled' | 'top' | 'bottom'>;
/**
* onMonthFormatter 用于设置月份的自定义数据
* @param month 原始数据
* @returns 返回新的数据
*/
onMonthFormatter?: (month: any) => {
title?: string;
className?: string;
};
}
export declare const CalendarDefaultProps: {
defaultValue: any;
value: any;
selectionMode: string;
monthRange: [number, number];
weekStartsOn: string;
localeText: {
weekdayNames: string[];
title: string;
today: string;
start: string;
end: string;
startAndEnd: string;
};
onFormatter: any;
onMonthFormatter: any;
changedScrollIntoView: any;
showSelectableDatesOnly: boolean;
};

View File

@ -0,0 +1,21 @@
import { defaultMonthRange } from './utils';
export var defaultLocaleText = {
weekdayNames: ['一', '二', '三', '四', '五', '六', '日'],
title: 'YYYY年MM月',
today: '今日',
start: '开始',
end: '结束',
startAndEnd: '开始/结束',
};
export var CalendarDefaultProps = {
defaultValue: null,
value: null,
selectionMode: 'range',
monthRange: defaultMonthRange(),
weekStartsOn: 'Sunday',
localeText: defaultLocaleText,
onFormatter: null,
onMonthFormatter: null,
changedScrollIntoView: null,
showSelectableDatesOnly: false,
};

View File

@ -0,0 +1,45 @@
function handleScroll(event, ownerComponent) {
var currentScroll = event.detail.scrollTop;
var dataset = event.instance.getDataset();
var elementSize = dataset.elementsize,
monthList = dataset.monthlist;
if (!elementSize) {
return;
}
// 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0
if (elementSize.cellHight === 0) {
ownerComponent.callMethod('measurement');
return;
}
var instance = ownerComponent.selectComponent('.ant-calendar-sticky-title');
var sticky = ownerComponent.selectComponent('.ant-calendar-sticky');
if (sticky) {
sticky.setStyle({
display: currentScroll < 0 ? 'none' : 'block'
});
}
var monthHeight = elementSize.monthTitleHeight;
var paddingHeight = elementSize.paddingHeight;
var cellHeight = elementSize.cellHight;
var heightList = monthList.map(function (p) {
return monthHeight + cellHeight * p.cells.length / 7;
});
for (var i = 0; i < heightList.length; i++) {
if (currentScroll < heightList[i]) {
var topHeight = currentScroll - heightList[i] + monthHeight - paddingHeight;
topHeight = Math.max(topHeight, 0);
instance.setStyle({
transform: "translateY(-".concat(topHeight, "px)")
});
ownerComponent.callMethod('setCurrentMonth', {
month: topHeight > monthHeight * 0.8 ? i + 1 : i
});
break;
} else {
currentScroll = currentScroll - heightList[i];
}
}
}
export default {
handleScroll: handleScroll
};

View File

@ -0,0 +1,14 @@
import { Dayjs } from 'dayjs';
import { CellState, LocaleText, SelectionMode, CalendarValue } from './props';
export declare function getMonthListFromRange(start: Dayjs, end: Dayjs): Dayjs[];
export declare function defaultMonthRange(): [number, number];
/**
*
* @param month 月份的某一天
* @param weekStartsOn 日历以星期几开始
* @returns 获取当月日历所有的日子
*/
export declare function getDate(month: Dayjs, weekStartsOn: string): Dayjs[];
export declare function renderCells(cellsMonth: Dayjs, weekStartsOn: string, value: CalendarValue, localeText: LocaleText, monthRangeList: Dayjs[]): CellState[];
export declare function getSelectionModeFromValue(value?: CalendarValue): SelectionMode;
export declare function getScrollIntoViewId(value: CalendarValue): string;

View File

@ -0,0 +1,157 @@
import dayjs from 'dayjs';
import { isoWeekday } from '../_util/dayjs/iso-weekday';
export function getMonthListFromRange(start, end) {
if (start.isAfter(end))
throw new Error("Start time can't be later than end time.");
var result = [];
var current = start.date(1);
while (!current.isAfter(end)) {
result.push(current.date(1));
current = current.add(1, 'month');
}
return result;
}
export function defaultMonthRange() {
var start = dayjs().startOf('date');
var end = dayjs().startOf('date').add(2, 'month');
return [start.toDate().getTime(), end.toDate().getTime()];
}
/**
*
* @param month 月份的某一天
* @param weekStartsOn 日历以星期几开始
* @returns 获取当月日历所有的日子
*/
export function getDate(month, weekStartsOn) {
var startOfMonth = month.date(1);
var cells = [];
var iterator = startOfMonth
.subtract(isoWeekday(startOfMonth) % 7, 'day')
.startOf('day');
if (weekStartsOn === 'Monday') {
iterator = iterator.add(1, 'day');
if (iterator.isSame(startOfMonth, 'month') &&
!iterator.isSame(startOfMonth.startOf('date'), 'date')) {
iterator = iterator.add(-7, 'days');
}
}
var diffDay = startOfMonth.date(1).add(1, 'month').diff(iterator, 'day');
var lintCount = Math.ceil(diffDay / 7);
while (cells.length < lintCount * 7) {
cells.push(iterator);
iterator = iterator.add(1, 'day');
}
return cells;
}
export function renderCells(cellsMonth, weekStartsOn, value, localeText, monthRangeList) {
var _a;
var rangeStartDate = monthRangeList[0], rangeEndDate = monthRangeList[1];
var rowBeginDay = 0;
var rowEndDay = 6;
if (weekStartsOn === 'Monday') {
rowBeginDay = 1;
rowEndDay = 0;
}
var dates = getDate(cellsMonth, weekStartsOn);
if (!value) {
return dates.map(function (d, index) {
var isToday = dayjs().isSame(d, 'day');
var isRowBegin = d.isSame(cellsMonth.startOf('month'), 'date') ||
d.day() === rowBeginDay;
var isRowEnd = d.isSame(cellsMonth.endOf('month'), 'date') || d.day() === rowEndDay;
var top;
if (isToday) {
top = {
label: localeText.today,
};
}
return {
index: index,
disabled: false,
time: d.toDate().getTime(),
date: d.get('date'),
isSelected: false,
isSelectedBegin: false,
top: top,
isSelectedEnd: false,
inThisMonth: d.month() === cellsMonth.month(),
isRowBegin: isRowBegin,
isRowEnd: isRowEnd,
isRange: (d.isSame(rangeStartDate) || d.isAfter(rangeStartDate)) &&
(d.isSame(rangeEndDate) || d.isBefore(rangeEndDate)),
};
});
}
var selectBegin;
var selectEnd;
if (Array.isArray(value)) {
selectBegin = dayjs(value[0]);
selectEnd = dayjs((_a = value[1]) !== null && _a !== void 0 ? _a : value[0]);
}
else {
selectBegin = dayjs(value);
selectEnd = dayjs(value);
}
return dates.map(function (d, index) {
var isToday = dayjs().isSame(d, 'day');
var isRowBegin = d.isSame(cellsMonth.startOf('month'), 'date') || d.day() === rowBeginDay;
var isRowEnd = d.isSame(cellsMonth.endOf('month'), 'date') || d.day() === rowEndDay;
var isSelectedBegin = selectBegin.isSame(d, 'day');
var isSelectedEnd = selectEnd.isSame(d, 'day');
var isSelected = (!!selectBegin.isBefore(d, 'day') && !!selectEnd.isAfter(d, 'day')) ||
isSelectedBegin ||
isSelectedEnd;
var inThisMonth = d.month() === cellsMonth.month();
var time = d.toDate().getTime();
var topLabel = isToday ? localeText.today : '';
if (Array.isArray(value)) {
if (isSelectedBegin) {
if (isSelectedEnd && value.length === 2) {
topLabel = localeText.startAndEnd;
}
else {
topLabel = localeText.start;
}
}
else {
if (isSelectedEnd) {
topLabel = localeText.end;
}
}
}
return {
index: index,
disabled: false,
time: time,
date: d.get('date'),
isSelected: isSelected,
isSelectedBegin: isSelectedBegin,
top: { label: topLabel },
isSelectedEnd: isSelectedEnd,
inThisMonth: inThisMonth,
isRowBegin: isRowBegin,
isRowEnd: isRowEnd,
isRange: (d.isSame(rangeStartDate) || d.isAfter(rangeStartDate)) &&
(d.isSame(rangeEndDate) || d.isBefore(rangeEndDate)),
};
});
}
export function getSelectionModeFromValue(value) {
if (Array.isArray(value)) {
return 'range';
}
if (typeof value === 'number') {
return 'single';
}
return null;
}
// 获取滚动视图的元素id
export function getScrollIntoViewId(value) {
// 已选中时间滚动到可视区域内微信不支持id为数字开头
return "id_".concat(value &&
dayjs(Array.isArray(value) ? value[0] : value)
.startOf('d')
.subtract(7, 'd') // 需要定位的地方往前推7天让已选中时间定位到中间位置
.toDate()
.getTime());
}

View File

@ -0,0 +1 @@
.ant-checkbox-group-horizontal .ant-checkbox-group-body{display:flex;flex-wrap:wrap;justify-content:flex-start}.ant-checkbox-group-horizontal .ant-checkbox-group-body .ant-list-item-line{padding-right:0}.ant-checkbox-group-horizontal .ant-checkbox-group-body .ant-checkbox-item{flex-flow:0}.ant-checkbox-group-horizontal .ant-checkbox-group-body .ant-list-item-line::after{display:none}.ant-checkbox-group-footer:empty,.ant-checkbox-group-header:empty{display:none}.ant-checkbox-group-footer,.ant-checkbox-group-header{display:flex;align-items:center;padding:8px 12px;line-height:1.4;font-size:15px;color:#999}.ant-checkbox-group-body{position:relative;overflow:hidden}.ant-checkbox-group-body .ant-checkbox-item-content .ant-checkbox-group-item-label-default:not(:nth-child(1)){display:none}

View File

@ -0,0 +1,70 @@
<import-sjs
from="../index.sjs"
name="componentUtils"
></import-sjs>
<list
className="ant-checkbox-group {{className ? className : ''}} ant-checkbox-group-{{position}}"
style="{{style}}"
>
<checkbox-group
name="{{name}}"
value="{{mixin.value}}"
>
<view class="ant-checkbox-group-body">
<block a:if="{{position === 'vertical'}}">
<block
a:for="{{options}}"
a:for-index="index"
a:for-item="item"
>
<list-item>
<ant-checkbox
color="{{color}}"
checked="{{componentUtils.getCheckboxChecked(item, mixin.value)}}"
data-index="{{index}}"
value="{{item.value}}"
disabled="{{disabled || item.disabled}}"
onChange="onChange"
>
<slot
name="label"
value="{{item}}"
index="{{index}}"
>
<view class="ant-checkbox-group-item-label-default">
{{item.label}}
</view>
</slot>
</ant-checkbox>
</list-item>
</block>
</block>
<block a:else>
<block
a:for="{{options}}"
a:for-index="index"
a:for-item="item"
>
<ant-checkbox
color="{{color}}"
checked="{{componentUtils.getCheckboxChecked(item, mixin.value)}}"
data-index="{{index}}"
value="{{item.value}}"
disabled="{{disabled || item.disabled}}"
onChange="onChange"
>
<slot
name="label"
value="{{item}}"
index="{{index}}"
>
<view class="ant-checkbox-group-item-label-default">
{{item.label}}
</view>
</slot>
</ant-checkbox>
</block>
</block>
</view>
</checkbox-group>
</list>

View File

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

View File

@ -0,0 +1,36 @@
import { __spreadArray } from "tslib";
import { Component, triggerEvent, getValueFromProps } from '../../_util/simply';
import { CheckboxGroupDefaultProps } from './props';
import mixinValue from '../../mixins/value';
Component(CheckboxGroupDefaultProps, {
onChange: function (args, e) {
if (getValueFromProps(this, 'disabled')) {
return;
}
var event;
event = e;
var currentValue = this.getValue();
var index = event.currentTarget.dataset.index;
var selectValue = getValueFromProps(this, 'options')[index].value;
if (currentValue.indexOf(selectValue) > -1) {
currentValue = currentValue.filter(function (v) { return v !== selectValue; });
}
else {
currentValue = __spreadArray(__spreadArray([], currentValue, true), [selectValue], false);
}
if (!this.isControlled()) {
this.update(currentValue);
}
triggerEvent(this, 'change', currentValue, e);
},
}, null, [
mixinValue({
transformValue: function (val) {
var value = val || [];
return {
needUpdate: true,
value: value,
};
},
}),
]);

View File

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {
"list": "../../List/index",
"list-item": "../../List/ListItem/index",
"ant-checkbox": "../index"
}
}

View File

@ -0,0 +1,15 @@
import { IBaseProps } from '../../_util/base';
export interface ICheckboxGroupProps extends IBaseProps {
value: string[];
defaultValue: string[];
disabled?: boolean;
position: 'horizontal' | 'vertical';
color: string;
options: {
label?: string;
value?: string;
disabled?: boolean;
}[];
onChange?: (value: string[], e: any) => void;
}
export declare const CheckboxGroupDefaultProps: Partial<ICheckboxGroupProps>;

View File

@ -0,0 +1,8 @@
export var CheckboxGroupDefaultProps = {
value: null,
defaultValue: [],
disabled: false,
position: 'vertical',
color: '',
options: [],
};

View File

@ -0,0 +1 @@
.ant-checkbox-item{color:#333;margin-right:8px}.ant-checkbox-item-container{display:flex;align-items:center}.ant-checkbox-item-content{padding-left:5px;text-align:left}.ant-checkbox-item-wrap{position:relative;width:22px;height:22px;flex:0 0 22px}.ant-checkbox-item-base{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0}.ant-checkbox-item-fake{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;pointer-events:none;display:flex;justify-content:center;align-items:center}.ant-checkbox-item-fake-icon{background-color:#fff;border:1px solid #ccc;border-radius:50vh;width:100%;height:100%;box-sizing:border-box}.ant-checkbox-item-fake-checkedIcon{border-radius:50vh;background-color:#1677ff;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.ant-checkbox-item-fake-checkedIcon-icon{color:#fff;font-size:14px}.ant-checkbox-item-fake-disbaledIcon{box-sizing:border-box;border:1px solid #ccc;border-radius:50vh;width:100%;height:100%;background-color:#f5f5f5}.ant-checkbox-item-fake-disabledCheckedIcon{box-sizing:border-box;border:1px solid #ccc;background-color:#f5f5f5;border-radius:50vh;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.ant-checkbox-item-fake-disabledCheckedIcon-icon{color:#ccc;font-size:14px}.ant-checkbox-item-disabled{opacity:.4}

View File

@ -0,0 +1,35 @@
<import-sjs
from="./index.sjs"
name="componentUtils"
></import-sjs>
<label
class="ant-checkbox-item {{className || ''}}"
style="{{style || ''}}"
>
<view class="ant-checkbox-item-container">
<view class="ant-checkbox-item-wrap">
<checkbox
class="ant-checkbox-item-base"
value="{{value}}"
onChange="onChange"
checked="{{mixin.value}}"
disabled="{{disabled}}"
></checkbox>
<view class="ant-checkbox-item-fake">
<view
class="ant-checkbox-item-fake-{{componentUtils.getClassName(mixin.value, disabled)}}"
style="{{mixin.value && !disabled && color ? 'background:' + color : ''}}"
>
<ant-icon
a:if="{{mixin.value}}"
type="CheckOutline"
className="ant-checkbox-item-fake-{{componentUtils.getClassName(mixin.value, disabled)}}-icon"
></ant-icon>
</view>
</view>
</view>
<view class="ant-checkbox-item-content {{disabled ? 'ant-checkbox-item-disabled' : ''}}">
<slot></slot>
</view>
</view>
</label>

View File

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

View File

@ -0,0 +1,17 @@
import { CheckboxDefaultProps } from './props';
import { Component, triggerEvent } from '../_util/simply';
import mixinValue from '../mixins/value';
Component(CheckboxDefaultProps, {
onChange: function (e) {
var value = !this.getValue();
if (!this.isControlled()) {
this.update(value);
}
triggerEvent(this, 'change', value, e);
},
}, null, [
mixinValue({
valueKey: 'checked',
defaultValueKey: 'defaultChecked',
}),
]);

View File

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

View File

@ -0,0 +1,21 @@
function getClassName(checked, disabled) {
if (!checked && !disabled) {
return 'icon';
}
if (checked && !disabled) {
return 'checkedIcon';
}
if (!checked && disabled) {
return 'disbaledIcon';
}
if (checked && disabled) {
return 'disabledCheckedIcon';
}
}
function getCheckboxChecked(item, value) {
return (value || []).indexOf(item.value) > -1;
}
export default {
getClassName: getClassName,
getCheckboxChecked: getCheckboxChecked
};

View File

@ -0,0 +1,13 @@
import { IBaseProps } from '../_util/base';
/**
* @description 复选框,表单组件。
*/
export interface ICheckboxProps extends IBaseProps {
value?: any;
checked: boolean;
defaultChecked?: boolean;
disabled: boolean;
color: string;
onChange?: (checked: boolean, e: any) => void;
}
export declare const CheckboxDefaultProps: Partial<ICheckboxProps>;

View File

@ -0,0 +1,7 @@
export var CheckboxDefaultProps = {
value: null,
checked: null,
defaultChecked: null,
disabled: false,
color: '',
};

View File

@ -0,0 +1 @@
.ant-checklist-item{background-color:#fff}.ant-checklist-item-hover{background-color:#eee}.ant-checklist-item-content{display:flex;align-items:center;padding:12px 12px;color:#333}.ant-checklist-item-content-disabled{opacity:.4}.ant-checklist-item-content-box{flex:1}.ant-checklist-item-content-box-nut{display:flex;align-items:center}.ant-checklist-item-image{width:36px;height:36px;border-radius:4px}.ant-checklist-item-text{flex:1;margin-left:12px}.ant-checklist-item-text-no-image{margin-left:0}.ant-checklist-item-text-title{color:#333;font-size:17px;line-height:24px}.ant-checklist-item-text-description{font-size:13px;color:#999;margin-top:1px;line-height:18px}.ant-checklist-item-checked-disabled{opacity:.4}.ant-checklist-item:last-child .ant-checklist-item-line{display:none}.ant-checklist-item-line{margin-left:12px;position:relative}.ant-checklist-item-line::after{content:'';position:absolute;background-color:#eee;display:block;top:auto;right:0;bottom:0;left:0;height:1px;transform:scaleY(.5)}

View File

@ -0,0 +1,23 @@
<view
class="ant-checklist-item"
onTap="{{item.disabled || item.readonly ? '' : 'onChecklistItemClick'}}"
hoverClass="{{item.disabled || item.readonly ? '' : 'ant-checklist-item-hover'}}"
hoverStartTime="{{20}}"
hoverStayTime="{{40}}"
>
<view class="ant-checklist-item-content {{item.disabled ? 'ant-checklist-item-content-disabled' : ''}}">
<view class="ant-checklist-item-content-box">
<slot
name="content"
item="{{item}}"
></slot>
</view>
<view
a:if="{{checked}}"
class="ant-checklist-item-content-icon"
>
<slot name="icon"></slot>
</view>
</view>
<view class="ant-checklist-item-line"></view>
</view>

View File

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

View File

@ -0,0 +1,7 @@
import { Component, triggerEvent, getValueFromProps } from '../../_util/simply';
import { ChecklistItemDefaultProps } from './props';
Component(ChecklistItemDefaultProps, {
onChecklistItemClick: function () {
triggerEvent(this, 'change', getValueFromProps(this, 'item'));
},
});

View File

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

View File

@ -0,0 +1,14 @@
import { IBaseProps } from '../../_util/base';
import { ChecklistItem } from '../props';
/**
* @description 可勾选列表单项
*/
export interface IChecklistItemProps extends IBaseProps {
item: ChecklistItem;
checked: boolean;
/**
* @description 当项选项值改变时触发
*/
onChange: (item: ChecklistItem) => void;
}
export declare const ChecklistItemDefaultProps: Partial<IChecklistItemProps>;

View File

@ -0,0 +1,4 @@
export var ChecklistItemDefaultProps = {
item: null,
checked: false,
};

View File

@ -0,0 +1 @@
.ant-checklist-body{position:relative;overflow:hidden}.ant-checklist-item-check-icon{font-size:18px;color:#1677ff}

View File

@ -0,0 +1,57 @@
<import-sjs
from="./index.sjs"
name="utils"
></import-sjs>
<view
class="ant-checklist {{className || ''}}"
style="{{style || ''}}"
>
<view class="ant-checklist-body">
<block
a:for="{{options}}"
a:for-index="index"
a:for-item="item"
>
<ant-checklist-item
checked="{{utils.getChecked(item.value, mixin.value, multiple)}}"
item="{{item}}"
onChange="onChange"
>
<view
slot="content"
class="ant-checklist-item-content-box-nut"
>
<slot
name="content"
item="{{item}}"
>
<image
a:if="{{item.image}}"
class="ant-checklist-item-image"
src="{{item.image}}"
></image>
<view class="ant-checklist-item-text {{item.image ? '' : 'ant-checklist-item-text-no-image'}}">
<view class="ant-checklist-item-text-title {{item.disabled ? 'ant-checklist-item-text-disabled' : ''}}">
{{item.title}}
</view>
<view
a:if="{{item.description}}"
class="ant-checklist-item-text-description {{item.disabled ? 'ant-checklist-item-text-disabled' : ''}}"
>
{{item.description}}
</view>
</view>
</slot>
</view>
<view slot="icon">
<slot name="icon">
<ant-icon
type="CheckOutline"
className="ant-checklist-item-check-icon"
></ant-icon>
</slot>
</view>
</ant-checklist-item>
</block>
</view>
</view>

View File

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

View File

@ -0,0 +1,49 @@
import { __spreadArray } from "tslib";
import { Component, triggerEventValues, getValueFromProps, } from '../_util/simply';
import { ChecklistDefaultProps } from './props';
import mixinValue from '../mixins/value';
Component(ChecklistDefaultProps, {
onChange: function (item) {
var _a = getValueFromProps(this, [
'multiple',
'options',
]), multiple = _a[0], options = _a[1];
var value;
value = item.value;
if (multiple) {
var currentValue_1 = this.getValue();
if (currentValue_1.indexOf(value) > -1) {
currentValue_1 = currentValue_1.filter(function (v) { return v !== value; });
}
else {
currentValue_1 = __spreadArray(__spreadArray([], currentValue_1, true), [value], false);
}
if (!this.isControlled()) {
this.update(currentValue_1);
}
triggerEventValues(this, 'change', [
currentValue_1,
options.filter(function (v) { return currentValue_1.indexOf(v.value) > -1; }),
]);
}
else {
if (!this.isControlled()) {
this.update(value);
}
triggerEventValues(this, 'change', [
value,
options.find(function (v) { return v.value === value; }),
]);
}
},
}, null, [
mixinValue({
transformValue: function (val) {
var value = val || [];
return {
needUpdate: true,
value: value,
};
},
}),
]);

View File

@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"ant-checklist-item": "./ChecklistItem/index",
"ant-icon": "../Icon/index"
}
}

View File

@ -0,0 +1,9 @@
function getChecked(value, values, multiple) {
if (!multiple) {
return value === values;
}
return (values || []).indexOf(value) > -1;
}
export default {
getChecked: getChecked
};

View File

@ -0,0 +1,48 @@
import { IBaseProps } from '../_util/base';
/**
* @description 可勾选列表
*/
export interface ChecklistItem {
/**
* @description 可勾选项的描述文案
*/
description?: string;
/**
* @description 可勾选项的图片地址
*/
image?: string;
/**
* @description 可勾选项的标题文案
*/
title: string;
/**
* @description 可勾选项的值
*/
value: string | number;
disabled?: boolean;
readonly?: boolean;
}
export interface IChecklistProps extends IBaseProps {
/**
* @description 默认值
*/
value: Array<string | number> | string | number;
/**
* @description 默认值
*/
defaultValue: Array<string | number> | string | number;
/**
* @description 是否支持多选
* @default false
*/
multiple: boolean;
/**
* @description 可勾选列表数据配置选项内容
*/
options: Array<ChecklistItem>;
/**
* @description 可勾选列表值改变时触发
*/
onChange: (v: Array<string | number> | string | number, item: ChecklistItem | Array<ChecklistItem>, e: Record<string, any>) => void;
}
export declare const ChecklistDefaultProps: Partial<IChecklistProps>;

View File

@ -0,0 +1,6 @@
export var ChecklistDefaultProps = {
value: null,
defaultValue: null,
options: [],
multiple: false,
};

View File

@ -0,0 +1 @@
.ant-collapse-item-disabled .ant-collapse-item-brief-container,.ant-collapse-item-disabled .ant-collapse-item-title-node{opacity:.4}.ant-collapse-item-disabled .ant-collapse-item-title:active{background:#fff;transition:0s}.ant-collapse-item-line{display:flex;flex:1;border-bottom:1px solid #eee;padding:0 12px 12px 0}.ant-collapse-item-title{position:relative;display:flex;text-align:justify;align-items:center;justify-content:space-between;line-height:24px;padding:12px 0 0 12px;font-size:17px;color:#333;background-color:#fff;transition:all .3s linear;box-sizing:border-box}.ant-collapse-item-title-node{display:flex;flex:1;max-width:100%;font-size:17px;color:#333}.ant-collapse-item-title-arrow{color:#ccc}.ant-collapse-item-title-icon{width:22px;height:22px;overflow:hidden;margin-right:12px}.ant-collapse-item-title-icon .ant-icon{font-size:20px}.ant-collapse-item-title-icon image{width:22px;height:22px}.ant-collapse-item-title:active{background-color:#eee;transition:0s}.ant-collapse-item-brief-container{display:flex}.ant-collapse-item-brief-container .ant-icon{font-size:20px}.ant-collapse-item-brief-node{display:flex;flex:1;font-size:15px;color:#999;margin-right:4px}.ant-collapse-item-content{color:#333;border-bottom:1px solid #eee;padding:12px 12px 12px 0;box-sizing:border-box}.ant-collapse-item-content-container{padding-left:12px;background:#fff}.ant-collapse-item-content-wrap{will-change:height;overflow:hidden}.ant-collapse-item-content-wrap-active{animation:trigger1 .2s}.ant-collapse-item-content-wrap-non-active{animation:trigger2 .2s}.ant-collapse-item-content-wrap-transition{transition:height .2s ease-in-out}.ant-collapse-item-content-wrap-first{height:0}@keyframes trigger1{0%{content:''}100%{content:''}}@keyframes trigger2{0%{content:''}100%{content:''}}

View File

@ -0,0 +1,78 @@
<import-sjs
from="./index.sjs"
name="utils"
></import-sjs>
<view
class="ant-collapse {{className ? className : ''}}"
style="{{style}}"
>
<block
a:for="{{items}}"
a:for-index="index"
a:for-item="item"
>
<view class="ant-collapse-item {{item.className || ''}} {{utils.isActive(mixin.value, index, item.disabled) ? 'ant-collapse-item-active' : ''}} {{item.disabled ? 'ant-collapse-item-disabled' : ''}}">
<view
class="ant-collapse-item-title"
data-active="{{utils.isActive(mixin.value, index, item.disabled)}}"
data-index="{{index}}"
data-id="{{$id}}"
onTap="onChange"
>
<view class="ant-collapse-item-line">
<view class="ant-collapse-item-title-node">
<slot
name="title"
value="{{item}}"
index="{{index}}"
current="{{mixin.value}}"
>
{{item.title}}
</slot>
</view>
<view class="ant-collapse-item-brief-container">
<view class="ant-collapse-item-brief-node">
<slot
name="brief"
value="{{item}}"
index="{{index}}"
current="{{mixin.value}}"
>
{{brief}}
</slot>
</view>
<view class="ant-collapse-item-title-arrow">
<slot
name="icon"
value="{{item}}"
index="{{index}}"
current="{{mixin.value}}"
>
<ant-icon type="{{utils.isActive(mixin.value, index, item.disabled) ? 'UpOutline' : 'DownOutline'}}"></ant-icon>
</slot>
</view>
</view>
</view>
</view>
<view
class="ant-collapse-item-content-wrap {{hasChange ? 'ant-collapse-item-content-wrap-transition' : ''}} ant-collapse-item-content-wrap{{$id ? '-' + $id : ''}}-{{index}}"
onTransitionEnd="resetContentHeight"
style="{{utils.getStyleHeight(index, contentHeight, item.disabled)}}"
data-index="{{index}}"
>
<view class="ant-collapse-item-content-container">
<view class="ant-collapse-item-content ant-collapse-item-content{{$id ? '-' + $id : ''}}-{{index}}">
<slot
name="content"
value="{{item}}"
index="{{index}}"
current="{{mixin.value}}"
>
{{item.content}}
</slot>
</view>
</view>
</view>
</view>
</block>
</view>

View File

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

View File

@ -0,0 +1,178 @@
import { __awaiter, __generator, __spreadArray } from "tslib";
import { Component, triggerEvent, getValueFromProps } from '../_util/simply';
import { CollapseDefaultProps } from './props';
import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect';
import createValue from '../mixins/value';
Component(CollapseDefaultProps, {
getInstance: function () {
if (this.$id) {
return my;
}
return this;
},
getBoundingClientRectWithBuilder: function (builder) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, getInstanceBoundingClientRect(this.getInstance(), builder(this.$id ? "-".concat(this.$id) : ''))];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
},
formatCurrent: function (val, props) {
var current = __spreadArray([], (val || []), true);
var items = props.items;
current = current.filter(function (item) {
if (!items[item] || items[item].disabled) {
return false;
}
return true;
});
if (props.accordion) {
current = current.length > 0 ? [current[0]] : [];
}
return __spreadArray([], current, true);
},
onChange: function (e) {
var itemIndex = parseInt(e.currentTarget.dataset.index, 10);
var _a = getValueFromProps(this, [
'items',
'accordion',
]), items = _a[0], accordion = _a[1];
if (items[itemIndex] && items[itemIndex].disabled) {
return;
}
var arr = this.getValue();
var current = __spreadArray([], arr, true);
var index = current.indexOf(itemIndex);
if (index >= 0) {
current.splice(index, 1);
}
else {
if (accordion) {
current = [itemIndex];
}
else {
current.push(itemIndex);
current.sort();
}
}
if (!this.isControlled()) {
this.update(current);
}
triggerEvent(this, 'change', current, e);
},
updateContentHeight: function (prevCurrent, nextCurrent) {
return __awaiter(this, void 0, void 0, function () {
var prevCurrentArray, nextCurrentArray, expandArray, closeArray, items, contentHeight;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
prevCurrentArray = prevCurrent;
nextCurrentArray = nextCurrent;
expandArray = [];
closeArray = [];
nextCurrentArray.forEach(function (item) {
if (prevCurrentArray.indexOf(item) < 0) {
expandArray.push(item);
}
});
prevCurrentArray.forEach(function (item) {
if (nextCurrentArray.indexOf(item) < 0) {
closeArray.push(item);
}
});
items = getValueFromProps(this, 'items');
return [4 /*yield*/, Promise.all(items.map(function (item, index) { return __awaiter(_this, void 0, void 0, function () {
var height;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(expandArray.indexOf(index) >= 0 ||
closeArray.indexOf(index) >= 0)) return [3 /*break*/, 2];
return [4 /*yield*/, this.getBoundingClientRectWithBuilder(function (id) { return ".ant-collapse-item-content".concat(id, "-").concat(index); })];
case 1:
height = (_a.sent()).height;
return [2 /*return*/, "".concat(height, "px")];
case 2: return [2 /*return*/, this.data.contentHeight[index]];
}
});
}); }))];
case 1:
contentHeight = _a.sent();
if (closeArray.length === 0) {
this.setData({
contentHeight: contentHeight,
});
}
else {
this.setData({
contentHeight: contentHeight,
});
setTimeout(function () {
contentHeight = contentHeight.map(function (item, index) {
if (closeArray.indexOf(index) >= 0) {
return '0px';
}
return item;
});
_this.setData({
contentHeight: contentHeight,
});
}, 10);
}
return [2 /*return*/];
}
});
});
},
resetContentHeight: function (e) {
var index = parseInt(e.currentTarget.dataset.index, 10);
if (this.getValue().indexOf(index) < 0) {
return;
}
var contentHeight = __spreadArray([], this.data.contentHeight, true);
contentHeight[index] = '';
this.setData({
contentHeight: contentHeight,
});
},
}, {
contentHeight: [],
hasChange: false,
}, [
createValue({
valueKey: 'current',
defaultValueKey: 'defaultCurrent',
transformValue: function (current, extra) {
var value = this.formatCurrent(current, extra ? extra.nextProps : getValueFromProps(this));
return {
needUpdate: true,
value: value,
};
},
}),
], {
didUpdate: function (prevProps, prevData) {
console.log(prevProps.items !== this.props.items, !this.isEqualValue(prevData));
if (prevProps.items !== this.props.items ||
!this.isEqualValue(prevData)) {
this.updateContentHeight(this.getValue(prevData), this.getValue());
}
},
didMount: function () {
var current = this.getValue();
var contentHeight = this.props.items.map(function (item, index) {
if (current.indexOf(index) >= 0) {
return '';
}
return '0px';
});
this.setData({
hasChange: true,
contentHeight: contentHeight,
});
},
});

View File

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

View File

@ -0,0 +1,23 @@
function isActive(current, index, disabled) {
if (disabled) {
return false;
}
return (current || []).indexOf(index) >= 0;
}
function getStyleHeight(index, contentHeight, disabled) {
if (disabled) {
return 'height: 0px';
}
var height = contentHeight[index];
if (height === '') {
return '';
}
if (height) {
return "height: ".concat(height);
}
return 'height: 0px';
}
export default {
isActive: isActive,
getStyleHeight: getStyleHeight
};

View File

@ -0,0 +1,35 @@
import { IBaseProps } from '../_util/base';
/**
* @description 手风琴
*/
export interface ICollapseProps extends IBaseProps {
/**
* @description 是否是手风琴模式,仅一个内容被展开
*/
/**
* @description 选中
*/
current?: number[];
/**
* @description 选中初始值
*/
defaultCurrent?: number[];
/**
* @description accordion模式
*/
accordion?: boolean;
/**
* @description 列表
*/
items?: {
title?: string;
content?: string;
disabled?: boolean;
className?: string;
}[];
/**
* @description collapse 切换时的回调
*/
onChange?: (current: number[] | undefined, e: Record<string, any>) => void;
}
export declare const CollapseDefaultProps: ICollapseProps;

View File

@ -0,0 +1,6 @@
export var CollapseDefaultProps = {
current: null,
defaultCurrent: [],
accordion: false,
items: [],
};

View File

@ -0,0 +1 @@
.ant-container{border-radius:8px;margin-bottom:12px}.ant-container-headerInBox{background-color:#fff}.ant-container-headerInBox .ant-container-header{padding:0 12px}.ant-container-headerInBox .ant-container-header .ant-container-header-right,.ant-container-headerInBox .ant-container-header .ant-container-header-title{position:relative}.ant-container-headerInBox .ant-container-header .ant-container-header-right::after,.ant-container-headerInBox .ant-container-header .ant-container-header-title::after{content:'';position:absolute;background-color:#eee;display:block;top:auto;right:0;bottom:0;left:0;height:1px;transform:scaleY(.5)}.ant-container-content{padding:12px;background-color:#fff;border-radius:8px}.ant-container-header{display:flex}.ant-container-header-title{font-size:16px;font-weight:700;color:#333;display:flex;align-items:center;height:48px;flex:1}.ant-container-header-title:empty{display:none}.ant-container-header-right{color:#999;display:flex;align-items:center;height:48px;justify-content:flex-end}.ant-container-header-right:empty{display:none}.ant-container-header .ant-container-header-title:empty+.ant-container-header-right:not(:empty){flex:1}

View File

@ -0,0 +1,16 @@
<view
class="ant-container {{headerInBox ? 'ant-container-headerInBox' : 'ant-container-headerNotInBox'}} {{className ? className : ''}}"
style="{{style}}"
>
<view class="ant-container-header">
<view class="ant-container-header-title">
<slot name="title">{{title}}</slot>
</view>
<view class="ant-container-header-right">
<slot name="headerRight"></slot>
</view>
</view>
<view class="ant-container-content">
<slot></slot>
</view>
</view>

View File

@ -0,0 +1 @@
import '../_util/assert-component2';

View File

@ -0,0 +1,5 @@
import { ContainerDefaultProps } from './props';
import '../_util/assert-component2';
Component({
props: ContainerDefaultProps,
});

View File

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

View File

@ -0,0 +1,24 @@
import { IBaseProps } from '../_util/base';
/**
* @description 容器,依据最佳实践统一了元素的间距、圆角,并可根据具体情况选择使用 title 内容。
*/
export interface IContainerProps extends IBaseProps {
/**
* @description 标题
*/
title?: string;
/**
* @description 标题是否在容器内
* @default true
*/
headerInBox?: boolean;
/**
* @description 类名
*/
className?: string;
/**
* @description 样式
*/
style?: string;
}
export declare const ContainerDefaultProps: IContainerProps;

View File

@ -0,0 +1,3 @@
export var ContainerDefaultProps = {
headerInBox: true,
};

View File

@ -0,0 +1 @@
.ant-range-picker-confirm-disabled .ant-picker-header-confirm{pointer-events:none;opacity:.6}.ant-range-picker-selector{display:flex;align-items:center;justify-content:space-between;height:52px;padding:12px 12px 0;box-sizing:border-box}.ant-range-picker-selector-item{width:155px;height:32px;padding:0 8px 0 12px;box-sizing:border-box;border-radius:4px;display:flex;justify-content:space-between;align-items:center;box-shadow:inset 0 .5px 3px 0 rgba(0,0,0,.1);color:#333}.ant-range-picker-selector-item-active{position:relative;color:#1677ff}.ant-range-picker-selector-item-active::before{content:'';position:absolute;top:0;left:0;width:200%;height:200%;transform-origin:0 0;pointer-events:none;border:1px solid #1677ff;border-radius:8px;transform:scale(.5);box-sizing:border-box}.ant-range-picker-selector-item-active .ant-range-picker-selector-item-icon{color:#1677ff}.ant-range-picker-selector-item-value{font-size:14px}.ant-range-picker-selector-item-placeholder{font-size:14px;color:#ccc}.ant-range-picker-selector-item-icon{color:#ccc;font-size:16px}.ant-range-picker-selector-split{color:#ccc}

View File

@ -0,0 +1,80 @@
<template name="selector">
<view
class="ant-range-picker-selector-item {{active ? 'ant-range-picker-selector-item-active' : ''}}"
onTap="onChangeCurrentPickerType"
data-type="{{type}}"
>
<view
a:if="{{value}}"
class="ant-range-picker-selector-item-value"
>
{{value}}
</view>
<view
a:else
class="ant-range-picker-selector-item-placeholder"
>
{{placeholder}}
</view>
<icon
a:if="{{precision === 'year' || precision === 'month' || precision === 'day' || precision === 'hour'}}"
type="CalendarOutline"
className="ant-range-picker-selector-item-icon"
></icon>
</view>
</template>
<ant-picker
formattedValueText="{{formattedValueText}}"
className="ant-range-picker {{className || ''}}"
popClassName="{{!currentStartDate || !currentEndDate ? 'ant-range-picker-confirm-disabled' : ''}} {{popClassName || ''}}"
visible="{{visible}}"
style="{{style}}"
animationType="{{animationType}}"
options="{{columns}}"
value="{{currentValue}}"
disabled="{{disabled}}"
title="{{title}}"
placeholder="{{placeholder}}"
okText="{{okText}}"
cancelText="{{cancelText}}"
maskStyle="{{maskStyle}}"
maskClassName="{{maskClassName}}"
indicatorStyle="{{indicatorStyle}}"
indicatorClassName="{{indicatorClassName}}"
onChange="onChange"
onCancel="onCancel"
onOk="onOk"
onVisibleChange="onVisibleChange"
maskClosable="{{maskClosable}}"
>
<view
class="ant-range-picker-selector"
slot="content-header"
>
<template
is="selector"
data="{{ placeholder: startPlaceholder, active: pickerType === 'start', type: 'start', value: currentStartValueStr, precision: precision }}"
></template>
<view class="ant-range-picker-selector-split">{{splitCharacter}}</view>
<template
is="selector"
data="{{ placeholder: endPlaceholder, active: pickerType === 'end', type: 'end', value: currentEndValueStr, precision: precision }}"
></template>
</view>
<slot
name="content"
slot="content"
></slot>
<slot
name="title"
slot="title"
></slot>
<slot
name="prefix"
slot="prefix"
></slot>
<slot
name="suffix"
slot="suffix"
></slot>
</ant-picker>

View File

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

View File

@ -0,0 +1,310 @@
import { Component, triggerEvent, triggerEventValues, triggerEventOnly, getValueFromProps, } from '../../_util/simply';
import { resolveEventValue, resolveEventValues } from '../../_util/platform';
import { DateRangePickerDefaultProps } from './props';
import dayjs from 'dayjs';
import equal from 'fast-deep-equal';
import { getRangeData, getDateByValue, getValueByDate, getValidValue, } from '../util';
import computed from '../../mixins/computed';
import mixinValue from '../../mixins/value';
Component(DateRangePickerDefaultProps, {
// visible受控判断
isVisibleControlled: function () {
return 'visible' in getValueFromProps(this);
},
computed: function () {
var _a = this.data, currentStartDate = _a.currentStartDate, currentEndDate = _a.currentEndDate, pickerType = _a.pickerType;
var format = getValueFromProps(this, 'format');
if (pickerType)
return {
currentStartValueStr: currentStartDate
? dayjs(currentStartDate).format(format)
: '',
currentEndValueStr: currentEndDate
? dayjs(currentEndDate).format(format)
: '',
};
},
getMin: function (min) {
return min ? dayjs(min) : dayjs().subtract(10, 'year');
},
getMax: function (max) {
return max ? dayjs(max) : dayjs().add(10, 'year');
},
// didUpdate、弹窗打开、切换pickerType触发
setCurrentValue: function (currentProps) {
var _this = this;
var pickerVisible = this.pickerVisible; // 隐藏状态下从CValue触发展开状态使用当前数据
var precision = currentProps.precision;
var _a = this.data, pickerType = _a.pickerType, columns = _a.columns;
var realValue = this.getValue();
var _b = this.data, currentStartDate = _b.currentStartDate, currentEndDate = _b.currentEndDate;
var currentStartDateByCValue = (realValue === null || realValue === void 0 ? void 0 : realValue[0]) || null;
var currentEndDateByCValue = (realValue === null || realValue === void 0 ? void 0 : realValue[1]) || null;
// 展开状态说明在切换pickerType
if (pickerVisible) {
if (pickerType === 'start') {
if (!currentStartDate) {
currentStartDate = currentEndDate;
}
}
else {
// pickerType=end start已存在
// 结束时间默认选中开始
if (!currentEndDate) {
currentEndDate = currentStartDate;
}
}
}
else {
// 否则是在从cValue初始化
currentStartDate = currentStartDateByCValue;
currentEndDate = currentEndDateByCValue;
// 开始默认取优先取当前时间,不在时间范围内取开始时间
if (!currentStartDate) {
var min = this.getMin(currentProps.min).toDate();
var max = currentProps.max;
currentStartDate = new Date();
if ((min && dayjs(currentStartDate).isBefore(min, precision)) ||
(max && dayjs(currentStartDate).isAfter(max, precision)) ||
(currentEndDateByCValue &&
currentStartDate > currentEndDateByCValue)) {
currentStartDate = min;
}
}
}
var currentValue = getValueByDate(pickerType === 'start' ? currentStartDate : currentEndDate, precision);
var newColumns = this.generateData(currentValue, currentProps);
if (!equal(newColumns, columns)) {
this.setData({ columns: newColumns }, function () {
_this.setData({
currentStartDate: currentStartDate,
currentEndDate: currentEndDate,
currentValue: currentValue,
formattedValueText: _this.onFormat(),
});
});
}
else {
this.setData({
currentStartDate: currentStartDate,
currentEndDate: currentEndDate,
currentValue: currentValue,
formattedValueText: this.onFormat(),
});
}
},
/**
* 生成选项数据didmound、picker change、打开弹窗、切换picker type触发
*/
generateData: function (currentValue, currentProps) {
var precision = currentProps.precision, propsMin = currentProps.min, propsMax = currentProps.max;
var min = this.getMin(propsMin);
var max = this.getMax(propsMax);
if (max < min) {
return [];
}
var currentPickerDay = dayjs();
if (currentValue.length > 0) {
currentPickerDay = dayjs(getDateByValue(currentValue));
}
if (currentPickerDay < min || currentPickerDay > max) {
currentPickerDay = min;
}
var newColumns = getRangeData(precision, min, max, currentPickerDay, this.onFormatLabel.bind(this));
return newColumns;
},
onChange: function (selectedIdx) {
var _this = this;
var selectedIndex = resolveEventValues(getValidValue(selectedIdx))[0];
var _a = getValueFromProps(this, [
'format',
'precision',
'max',
'min',
]), format = _a[0], precision = _a[1], pmax = _a[2], pmin = _a[3];
var date = getDateByValue(selectedIndex);
var min = this.getMin(pmin);
var max = this.getMax(pmax);
if (dayjs(date).isBefore(min)) {
date = min.toDate();
selectedIndex = getValueByDate(date, precision);
}
if (dayjs(date).isAfter(max)) {
date = max.toDate();
selectedIndex = getValueByDate(date, precision);
}
var _b = this.data, pickerType = _b.pickerType, columns = _b.columns, currentEndDate = _b.currentEndDate, currentStartDate = _b.currentStartDate;
var newData = {
currentValue: selectedIndex,
formattedValueText: this.onFormat(),
};
if (pickerType === 'start') {
newData.currentStartDate = date;
if (currentEndDate && dayjs(date).isAfter(currentEndDate)) {
newData.currentEndDate = null;
}
}
else {
newData.currentEndDate = date;
if (currentStartDate && dayjs(date).isBefore(currentStartDate)) {
newData.currentStartDate = null;
}
}
var newColumns = this.generateData(selectedIndex, getValueFromProps(this));
if (!equal(newColumns, columns)) {
this.setData({
columns: newColumns,
}, function () {
_this.setData(newData);
triggerEventValues(_this, 'pickerChange', [
pickerType,
date,
dayjs(date).format(format),
]);
});
}
else {
this.setData(newData);
triggerEventValues(this, 'pickerChange', [
pickerType,
date,
dayjs(date).format(format),
]);
}
},
onCancel: function (e) {
triggerEventOnly(this, 'cancel', e);
},
onOk: function () {
var format = getValueFromProps(this, 'format');
var _a = this.data, currentStartDate = _a.currentStartDate, currentEndDate = _a.currentEndDate;
var realValue = [currentStartDate, currentEndDate];
if (!this.isControlled()) {
this.update(realValue);
}
triggerEventValues(this, 'ok', [
realValue,
realValue.map(function (v) { return dayjs(v).format(format); }),
]);
},
onFormatLabel: function (type, value) {
var onFormatLabel = getValueFromProps(this, 'onFormatLabel');
var formatValueByProps = onFormatLabel && onFormatLabel(type, value);
if (formatValueByProps !== undefined && formatValueByProps !== null) {
return String(formatValueByProps);
}
return this.defaultFormatLabel(type, value);
},
defaultFormatLabel: function (type, value) {
var suffixMap = {
year: '年',
month: '月',
day: '日',
hour: '时',
minute: '分',
second: '秒',
};
return "".concat(value).concat(suffixMap[type]);
},
defaultFormat: function (date, valueStrs) {
var _a = getValueFromProps(this, [
'format',
'splitCharacter',
]), format = _a[0], splitCharacter = _a[1];
if (format && valueStrs && valueStrs[0] && valueStrs[1]) {
return valueStrs.join("".concat(splitCharacter));
}
return '';
},
onFormat: function () {
var _a = getValueFromProps(this, [
'onFormat',
'format',
]), onFormat = _a[0], format = _a[1];
var realValue = this.getValue();
var formatValueByProps = onFormat &&
onFormat(realValue, realValue
? realValue.map(function (v) { return (v ? dayjs(v).format(format) : null); })
: null);
if (formatValueByProps !== undefined && formatValueByProps !== null) {
return formatValueByProps;
}
return this.defaultFormat(realValue, realValue
? realValue.map(function (v) { return (v ? dayjs(v).format(format) : null); })
: null);
},
/**
* 显示/隐藏切换
* @param visible
*/
onVisibleChange: function (visible) {
if (!this.isVisibleControlled() && visible) {
this.setData({ pickerType: 'start' });
this.setCurrentValue(getValueFromProps(this));
this.pickerVisible = visible;
}
triggerEvent(this, 'visibleChange', resolveEventValue(visible));
},
onChangeCurrentPickerType: function (e) {
var type = e.currentTarget.dataset.type;
var pickerType = this.data.pickerType;
if (type !== pickerType) {
this.setData({
pickerType: type,
});
this.setCurrentValue(getValueFromProps(this));
}
},
}, {
currentValue: [],
columns: [],
pickerType: 'start',
currentStartDate: null,
currentEndDate: null,
forceUpdate: 0,
formattedValueText: '',
}, [
mixinValue({
transformValue: function (value) {
return {
value: value && value[0] && value[1]
? [dayjs(value[0]).toDate(), dayjs(value[1]).toDate()]
: undefined,
needUpdate: true,
};
},
}),
computed(),
], {
pickerVisible: false,
didMount: function () {
this.pickerVisible = false;
var _a = getValueFromProps(this, [
'visible',
'defaultVisible',
]), visible = _a[0], defaultVisible = _a[1];
this.setData({
visible: this.isVisibleControlled() ? visible : defaultVisible,
formattedValueText: this.onFormat(),
});
},
didUpdate: function (prevProps, prevData) {
var currentProps = getValueFromProps(this);
var visible = getValueFromProps(this, 'visible');
if (this.isVisibleControlled() && !equal(prevProps.visible, visible)) {
this.setData({ visible: visible });
this.setCurrentValue(currentProps);
this.pickerVisible = visible;
}
if (!this.isEqualValue(prevData)) {
this.setData({
forceUpdate: this.data.forceUpdate + 1,
formattedValueText: this.onFormat(),
});
if (this.pickerVisible) {
// 展开状态才更新picker的数据否则下次triggerVisible触发
this.setCurrentValue(currentProps);
}
}
},
});

View File

@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"icon": "../../Icon/index",
"ant-picker": "../../Picker/index"
}
}

View File

@ -0,0 +1,139 @@
import { IBaseProps } from '../../_util/base';
export type PickerValue = [Date, Date];
/**
* @description 对话框
*/
export interface IDateRangePickerProps extends IBaseProps {
visible?: boolean;
defaultVisible?: boolean;
/**
* @desciption 动画类型
* @default "transform"
*/
animationType: 'transform' | 'position';
/**
* @description 时间格式化显示例如YYYY-MM-DD
*/
format: string;
/**
* @description 最小值
* @default 十年前
*/
min: Date;
/**
* @description 最大值
* @default 十年后
*/
max: Date;
/**
* @description 当前数据
*/
value: PickerValue;
/**
* @description 默认值
*/
defaultValue: PickerValue;
/**
* @description 标题
*/
title: string;
/**
* @description 确定按钮文案
* @default "确定"
*/
okText: string;
/**
* @description 取消文案
* @default "取消"
*/
cancelText: string;
/**
* @description 提示文案
* @default '请选择'
*/
placeholder: string;
/**
* @description 是否禁用
*/
disabled?: boolean;
/**
*@description 选中框样式
* 版本要求: 支付宝小程序基础库 1.10.0 及以上
*/
indicatorStyle?: string;
/**
*@description 选中框类名
* 版本要求: 支付宝小程序基础库 1.10.0 及以上
*/
indicatorClassName?: string;
/**
* @description 蒙层的样式。
* 版本要求: 支付宝小程序基础库 1.10.0 及以上
*/
maskStyle?: string;
/**
* @description 蒙层的类名。
* 版本要求: 支付宝小程序基础库 1.10.0 及以上
*/
maskClassName?: string;
/**
* @description 点击确认回调
*/
onOk?: (date: PickerValue, dateStr: [string, string], e: Record<string, any>) => void;
/**
* @description 点击取消回调
*/
onCancel?: (e: Record<string, any>) => void;
/**
* @description 发生滚动即触发, 与 onChange 点击 ok 后触发不同
*/
onPickerChange?: (type: 'start' | 'end', date: Date, dateStr: string, e: Record<string, any>) => void;
/**
* @description 精度
* @default 'day'
*/
precision: 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second';
/**
* @description 选中值的文本显示格式
*/
onFormat?: (date: PickerValue, dateStr: [string, string]) => string;
/**
* @description 切换显示隐藏
*/
onVisibleChange?: (visible: any, e: Record<string, any>) => void;
/**
* @description 显示连接符
* @default '-''
*/
splitCharacter: string;
/**
* @description 开始时间提示文案
* @default '未选择'
*/
startPlaceholder: string;
/**
* @description 结束时间提示文案
* @default '未选择'
*/
endPlaceholder: string;
/**
* @description 点击蒙层是否可以关闭
* @default false
*/
maskClosable: boolean;
/**
* @description 弹出框类名
*/
popClassName: string;
/**
* @description 弹出框样式
*/
popStyle: string;
/**
* 自定义每列展示的内容
* @param type
* @param value
*/
onFormatLabel?(type: 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second', value: number): string;
}
export declare const DateRangePickerDefaultProps: Partial<IDateRangePickerProps>;

View File

@ -0,0 +1,24 @@
export var DateRangePickerDefaultProps = {
visible: null,
defaultVisible: null,
animationType: 'transform',
format: 'YYYY/MM/DD',
min: null,
max: null,
value: null,
defaultValue: null,
title: '',
okText: '确定',
cancelText: '取消',
placeholder: '请选择',
precision: 'day',
splitCharacter: '-',
startPlaceholder: '未选择',
endPlaceholder: '未选择',
maskClosable: true,
popClassName: '',
popStyle: '',
disabled: false,
onFormatLabel: null,
onFormat: null,
};

View File

@ -0,0 +1,42 @@
<ant-picker
className="ant-date-picker"
popClassName="ant-date-picker-popup {{popClassName || ''}}"
visible="{{visible}}"
style="{{style}}"
popStyle="{{popStyle}}"
animationType="{{animationType}}"
options="{{columns}}"
value="{{currentValue}}"
disabled="{{disabled}}"
title="{{title}}"
placeholder="{{placeholder}}"
okText="{{okText}}"
cancelText="{{cancelText}}"
maskStyle="{{maskStyle}}"
maskClassName="{{maskClassName}}"
indicatorStyle="{{indicatorStyle}}"
indicatorClassName="{{indicatorClassName}}"
onChange="onChange"
onCancel="onCancel"
onOk="onOk"
formattedValueText="{{formattedValueText}}"
onVisibleChange="onVisibleChange"
maskClosable="{{maskClosable}}"
>
<slot
name="content"
slot="content"
></slot>
<slot
name="title"
slot="title"
></slot>
<slot
name="prefix"
slot="prefix"
></slot>
<slot
name="suffix"
slot="suffix"
></slot>
</ant-picker>

View File

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

View File

@ -0,0 +1,222 @@
import { Component, triggerEvent, triggerEventOnly, triggerEventValues, getValueFromProps, } from '../_util/simply';
import { resolveEventValue, resolveEventValues } from '../_util/platform';
import { DatePickerDefaultProps } from './props';
import dayjs from 'dayjs';
import equal from 'fast-deep-equal';
import { getRangeData, getDateByValue, getValueByDate, getValidValue, } from './util';
import mixinValue from '../mixins/value';
Component(DatePickerDefaultProps, {
// visible受控判断
isVisibleControlled: function () {
return 'visible' in getValueFromProps(this);
},
// 当前选中的picker值处理无cValue时的情况优先取当前时间不在时间范围内取开始时间
getCurrentValueWithCValue: function (currentProps) {
var realValue = this.getValue();
var min = currentProps.min, max = currentProps.max, precision = currentProps.precision;
if (realValue) {
return getValueByDate(realValue, precision);
}
else {
var now = new Date();
if (!(min && dayjs(now).isBefore(dayjs(min), precision)) &&
!(max && dayjs(now).isAfter(dayjs(max), precision))) {
return getValueByDate(now, precision);
}
else {
return getValueByDate(this.getMin(min).toDate(), precision);
}
}
},
getMin: function (min) {
return min ? dayjs(min) : dayjs().subtract(10, 'year');
},
getMax: function (max) {
return max ? dayjs(max) : dayjs().add(10, 'year');
},
/**
* didUpdate、弹窗打开触发
*/
setCurrentValue: function (currentProps) {
var _this = this;
var currentValue = this.getCurrentValueWithCValue(currentProps);
var newColumns = this.generateData(currentValue, currentProps);
if (!equal(newColumns, this.data.columns)) {
this.setData({
columns: newColumns,
}, function () {
_this.setData({
currentValue: currentValue,
formattedValueText: _this.onFormat(),
});
});
}
},
// 生成选项数据didmound、picker change、打开弹窗触发
generateData: function (currentValue, currentProps) {
var precision = currentProps.precision, propsMin = currentProps.min, propsMax = currentProps.max;
var min = this.getMin(propsMin);
var max = this.getMax(propsMax);
if (max < min) {
return [];
}
var currentPickerDay = dayjs();
if (currentValue.length > 0) {
currentPickerDay = dayjs(getDateByValue(currentValue));
}
if (currentPickerDay < min || currentPickerDay > max) {
currentPickerDay = min;
}
var newColumns = getRangeData(precision, min, max, currentPickerDay, this.onFormatLabel.bind(this));
return newColumns;
},
onFormatLabel: function (type, value) {
var onFormatLabel = getValueFromProps(this, 'onFormatLabel');
var formatValueByProps = onFormatLabel && onFormatLabel(type, value);
if (formatValueByProps !== undefined && formatValueByProps !== null) {
return String(formatValueByProps);
}
return this.defaultFormatLabel(type, value);
},
defaultFormatLabel: function (type, value) {
var suffixMap = {
year: '年',
month: '月',
day: '日',
hour: '时',
minute: '分',
second: '秒',
};
return "".concat(value).concat(suffixMap[type]);
},
onChange: function (selectedIdx) {
var _this = this;
var _a = getValueFromProps(this, [
'min',
'max',
'format',
'precision',
]), pmin = _a[0], pmax = _a[1], format = _a[2], precision = _a[3];
var selectedIndex = resolveEventValues(getValidValue(selectedIdx))[0];
var date = getDateByValue(selectedIndex);
var min = this.getMin(pmin);
var max = this.getMax(pmax);
if (dayjs(date).isBefore(min)) {
date = min.toDate();
selectedIndex = getValueByDate(date, precision);
}
if (dayjs(date).isAfter(max)) {
date = max.toDate();
selectedIndex = getValueByDate(date, precision);
}
var newColumns = this.generateData(selectedIndex, getValueFromProps(this));
if (!equal(newColumns, this.data.columns)) {
this.setData({
columns: newColumns,
}, function () {
_this.setData({ currentValue: selectedIndex });
var date = getDateByValue(selectedIndex);
triggerEventValues(_this, 'pickerChange', [
date,
dayjs(date).format(format),
]);
});
}
else {
this.setData({ currentValue: selectedIndex });
var date_1 = getDateByValue(selectedIndex);
triggerEventValues(this, 'pickerChange', [
date_1,
dayjs(date_1).format(format),
]);
}
},
onCancel: function (e) {
triggerEventOnly(this, 'cancel', e);
},
onOk: function () {
var currentValue = this.data.currentValue;
var format = getValueFromProps(this, 'format');
var date = getDateByValue(currentValue);
if (!this.isControlled()) {
this.update(date);
}
triggerEventValues(this, 'ok', [date, dayjs(date).format(format)]);
},
defaultFormat: function (value, valueStr) {
var format = getValueFromProps(this, 'format');
if (format && valueStr) {
return valueStr;
}
return '';
},
onFormat: function () {
var _a = getValueFromProps(this, [
'format',
'onFormat',
]), format = _a[0], onFormat = _a[1];
var realValue = this.getValue();
var formatValueByProps = onFormat &&
onFormat(realValue, realValue ? dayjs(realValue).format(format) : null);
if (formatValueByProps !== undefined && formatValueByProps !== null) {
return formatValueByProps;
}
return this.defaultFormat(realValue, realValue ? dayjs(realValue).format(format) : null);
},
onVisibleChange: function (visible) {
this.pickerVisible = visible;
if (!this.isVisibleControlled() && visible) {
this.setCurrentValue(getValueFromProps(this));
}
triggerEvent(this, 'visibleChange', resolveEventValue(visible));
},
}, {
currentValue: [],
formattedValueText: '',
columns: [],
forceUpdate: 0,
visible: null,
}, [
mixinValue({
transformValue: function (value) {
return {
value: value ? dayjs(value).toDate() : undefined,
needUpdate: true,
};
},
}),
], {
pickerVisible: false,
onInit: function () {
this.pickerVisible = false;
var _a = getValueFromProps(this, [
'visible',
'defaultVisible',
]), visible = _a[0], defaultVisible = _a[1];
this.setData({
visible: this.isVisibleControlled() ? visible : defaultVisible,
formattedValueText: this.onFormat(),
});
},
didUpdate: function (prevProps, prevData) {
var currentProps = getValueFromProps(this);
var visible = getValueFromProps(this, 'visible');
if (this.isVisibleControlled() && !equal(prevProps.visible, visible)) {
this.pickerVisible = visible;
this.setData({ visible: visible });
if (this.pickerVisible) {
this.setCurrentValue(currentProps);
}
}
if (!this.isEqualValue(prevData)) {
this.setData({
forceUpdate: this.data.forceUpdate + 1,
formattedValueText: this.onFormat(),
});
// 展开状态才更新picker的数据否则下次triggerVisible触发
if (this.pickerVisible) {
this.setCurrentValue(currentProps);
}
}
},
});

View File

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"ant-picker": "../Picker/index"
}
}

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