mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
暂存表单修改
This commit is contained in:
parent
27a4083a1c
commit
d68cda753b
@ -678,7 +678,7 @@ order: 31
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
searchable: true,
|
searchable: true,
|
||||||
multiple: false,
|
multiple: true,
|
||||||
joinValues: true,
|
joinValues: true,
|
||||||
clearable: true
|
clearable: true
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ order: 68
|
|||||||
```schema: scope="body"
|
```schema: scope="body"
|
||||||
{
|
{
|
||||||
"type": "tabs",
|
"type": "tabs",
|
||||||
|
"swipeable": true,
|
||||||
"tabs": [
|
"tabs": [
|
||||||
{
|
{
|
||||||
"title": "Tab 1",
|
"title": "Tab 1",
|
||||||
@ -23,6 +24,54 @@ order: 68
|
|||||||
{
|
{
|
||||||
"title": "Tab 2",
|
"title": "Tab 2",
|
||||||
"tab": "Content 2"
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 3",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 4",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 5",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 6",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 7",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 8",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 9",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 10",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 11",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 12",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 13",
|
||||||
|
"tab": "Content 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Tab 14",
|
||||||
|
"tab": "Content 2"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -789,6 +838,7 @@ order: 68
|
|||||||
| sidePosition | `left` / `right` | `left` | `sidebar` 模式下,标签栏位置 |
|
| sidePosition | `left` / `right` | `left` | `sidebar` 模式下,标签栏位置 |
|
||||||
| collapseOnExceed | `number` | | 当 tabs 超出多少个时开始折叠 |
|
| collapseOnExceed | `number` | | 当 tabs 超出多少个时开始折叠 |
|
||||||
| collapseBtnLabel | `string` | `more` | 用来设置折叠按钮的文字 |
|
| collapseBtnLabel | `string` | `more` | 用来设置折叠按钮的文字 |
|
||||||
|
| swipeable | `boolean` | false | 是否开启手势滑动切换(移动端生效) |
|
||||||
|
|
||||||
## 事件表
|
## 事件表
|
||||||
|
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
export default {
|
export default {
|
||||||
type: 'page',
|
type: 'page',
|
||||||
title: '表单页面',
|
body: {
|
||||||
body: [
|
type: 'form',
|
||||||
{
|
body: [
|
||||||
type: 'form',
|
{
|
||||||
mode: 'horizontal',
|
label: '多选',
|
||||||
api: '/api/mock2/form/saveForm',
|
type: 'select',
|
||||||
body: [
|
name: 'select2',
|
||||||
{
|
searchable: true,
|
||||||
label: 'Name',
|
checkAll: true,
|
||||||
type: 'input-text',
|
multiple: true,
|
||||||
name: 'name'
|
clearable: true,
|
||||||
},
|
source: '/api/mock2/form/getOptions'
|
||||||
{
|
}
|
||||||
label: 'Email',
|
]
|
||||||
type: 'input-email',
|
}
|
||||||
placeholder: '请输入邮箱地址',
|
|
||||||
name: 'email'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
@ -1676,6 +1676,8 @@
|
|||||||
--InputRange-track-onActive-bg: var(--colors-brand-5);
|
--InputRange-track-onActive-bg: var(--colors-brand-5);
|
||||||
--InputRange-handle-height: var(--sizes-size-9);
|
--InputRange-handle-height: var(--sizes-size-9);
|
||||||
--InputRange-handle-width: var(--sizes-size-9);
|
--InputRange-handle-width: var(--sizes-size-9);
|
||||||
|
--InputRange-handle-mobile-height: var(--sizes-base-11);
|
||||||
|
--InputRange-handle-mobile-width: var(--sizes-base-11);
|
||||||
--InputRange-handle-bg: var(--colors-neutral-fill-11);
|
--InputRange-handle-bg: var(--colors-neutral-fill-11);
|
||||||
--InputRange-handle-top-border-color: var(--colors-brand-5);
|
--InputRange-handle-top-border-color: var(--colors-brand-5);
|
||||||
--InputRange-handle-top-border-width: 0.0625rem;
|
--InputRange-handle-top-border-width: 0.0625rem;
|
||||||
@ -1730,6 +1732,7 @@
|
|||||||
);
|
);
|
||||||
--InputRange-label-position-bottom: calc(100% + 8px);
|
--InputRange-label-position-bottom: calc(100% + 8px);
|
||||||
--InputRange-input-width: var(--sizes-base-40);
|
--InputRange-input-width: var(--sizes-base-40);
|
||||||
|
--InputRange-input-mobile-width: var(--sizes-base-20);
|
||||||
--InputRange-input-marginTop: var(--sizes-size-0);
|
--InputRange-input-marginTop: var(--sizes-size-0);
|
||||||
--InputRange-input-marginBottom: var(--sizes-size-0);
|
--InputRange-input-marginBottom: var(--sizes-size-0);
|
||||||
--InputRange-input-marginLeft: var(--sizes-size-5);
|
--InputRange-input-marginLeft: var(--sizes-size-5);
|
||||||
@ -2821,6 +2824,7 @@
|
|||||||
--select-tree-active-bg-color: var(--colors-brand-10);
|
--select-tree-active-bg-color: var(--colors-brand-10);
|
||||||
|
|
||||||
--Form-select-bg: var(--select-base-default-bg-color);
|
--Form-select-bg: var(--select-base-default-bg-color);
|
||||||
|
--Form-select-mobile-icon-check-color: var(--colors-brand-5);
|
||||||
--Form-select-height: var(--Form-select-outer-top);
|
--Form-select-height: var(--Form-select-outer-top);
|
||||||
--Form-select-borderColor: var(--select-base-default-top-border-color)
|
--Form-select-borderColor: var(--select-base-default-top-border-color)
|
||||||
var(--select-base-default-right-border-color)
|
var(--select-base-default-right-border-color)
|
||||||
|
@ -527,6 +527,10 @@ $Table-strip-bg: transparent;
|
|||||||
--ListMenu-item-bg: var(--colors-neutral-fill-11);
|
--ListMenu-item-bg: var(--colors-neutral-fill-11);
|
||||||
--ListMenu-item-color: var(--colors-neutral-text-2);
|
--ListMenu-item-color: var(--colors-neutral-text-2);
|
||||||
--ListMenu-item-height: var(--sizes-base-15);
|
--ListMenu-item-height: var(--sizes-base-15);
|
||||||
|
--ListMenu-item-mobile-margin: #{px2rem(5px)};
|
||||||
|
--ListMenu-item-mobile-width: #{px2rem(90px)};
|
||||||
|
--ListMenu-item-mobile-bg: #f5f5f5;
|
||||||
|
--ListMenu-item-mobile-active-bg: #e7f1ff;
|
||||||
|
|
||||||
--Log-bg: #222;
|
--Log-bg: #222;
|
||||||
--Log-padding: var(--gap-sm) 0;
|
--Log-padding: var(--gap-sm) 0;
|
||||||
@ -768,6 +772,11 @@ $Table-strip-bg: transparent;
|
|||||||
--UserSelect--border-color: #f7f7f9;
|
--UserSelect--border-color: #f7f7f9;
|
||||||
--UserSelect--content-bg: #f5f7f8;
|
--UserSelect--content-bg: #f5f7f8;
|
||||||
--UserSelect--bread-color: #5e626a;
|
--UserSelect--bread-color: #5e626a;
|
||||||
|
|
||||||
|
--Cascader-border-color: #f7f7f9;
|
||||||
|
--Cascader-border-active-bg-color: #f7f7f9;
|
||||||
|
--Cascader-option-disable-color: #b8babf;
|
||||||
|
|
||||||
// tag
|
// tag
|
||||||
--Tag-content-fontSize: var(--fontSizeSm);
|
--Tag-content-fontSize: var(--fontSizeSm);
|
||||||
--Tag-height: #{px2rem(24px)};
|
--Tag-height: #{px2rem(24px)};
|
||||||
|
@ -123,8 +123,15 @@
|
|||||||
border-width: 0;
|
border-width: 0;
|
||||||
|
|
||||||
&--time {
|
&--time {
|
||||||
height: fit-content;
|
height: px2rem(360px);
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
|
.#{$ns}PopUp-content {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--years {
|
||||||
|
height: px2rem(360px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,6 +253,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: px2rem(4px);
|
border-radius: px2rem(4px);
|
||||||
|
padding: 0 px2rem(10px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,11 +290,11 @@
|
|||||||
line-height: px2rem(48px);
|
line-height: px2rem(48px);
|
||||||
}
|
}
|
||||||
.#{$ns}DateRangePicker-rangers {
|
.#{$ns}DateRangePicker-rangers {
|
||||||
position: absolute;
|
padding-left: revert;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
.#{$ns}DateRangePicker-ranger {
|
line-height: inherit;
|
||||||
margin: 0 px2rem(25px);
|
display: flex;
|
||||||
}
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.#{$ns}DatePicker-shortcuts {
|
.#{$ns}DatePicker-shortcuts {
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
height: px2rem(260px);
|
height: px2rem(260px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
padding-left: px2rem(10px);
|
||||||
|
border: 1px solid var(--Cascader-border-color);
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -52,13 +55,18 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: px2rem(6px) 0;
|
padding: px2rem(6px) 0 px2rem(6px) px2rem(10px);
|
||||||
font-size: var(--fontSizeMd);
|
font-size: var(--fontSizeMd);
|
||||||
line-height: var(--Cascader-option-lineHeight);
|
line-height: var(--Cascader-option-lineHeight);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background-color: var(--Cascader-border-active-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
span {
|
.#{$ns}Cascader-option--text {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,11 +76,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&--text {
|
&--text {
|
||||||
|
flex: 1;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
color: var(--Cascader-option-disable-color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-arrow {
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: px2rem(6px);
|
||||||
|
> svg {
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-selectedNum {
|
&-selectedNum {
|
||||||
min-width: px2rem(16px);
|
min-width: px2rem(16px);
|
||||||
height: px2rem(16px);
|
height: px2rem(16px);
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}Collapse:not(:last-child) {
|
.#{$ns}Collapse:not(:last-child):not(.is-mobile) {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,4 +40,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
&.icon-position-right {
|
||||||
|
.#{$ns}Collapse-header {
|
||||||
|
.#{$ns}Collapse-arrow-wrap {
|
||||||
|
margin-right: px2rem(-18px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,17 @@
|
|||||||
background: var(--Collapse-header-onHover-bg);
|
background: var(--Collapse-header-onHover-bg);
|
||||||
color: var(--collapse-default-header-hover-color);
|
color: var(--collapse-default-header-hover-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
background: none;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Collapse-arrow {
|
.Collapse-arrow {
|
||||||
@ -76,7 +87,7 @@
|
|||||||
// display: inline-block;
|
// display: inline-block;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
&.is-active > &-header > &-arrow-wrap > &-arrow {
|
&.is-active > .#{$ns}Collapse-header > .#{$ns}Collapse-arrow-wrap > &-arrow {
|
||||||
transform: rotate(var(--collapse-icon-rotate));
|
transform: rotate(var(--collapse-icon-rotate));
|
||||||
transform-origin: 50% 50%;
|
transform-origin: 50% 50%;
|
||||||
}
|
}
|
||||||
@ -133,6 +144,28 @@
|
|||||||
line-height: var(--collapse-default-content-lineHeight);
|
line-height: var(--collapse-default-content-lineHeight);
|
||||||
background: var(--collapse-default-bg-color);
|
background: var(--collapse-default-bg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}Collapse-icon-tranform,
|
||||||
|
.#{$ns}Collapse-arrow-wrap {
|
||||||
|
margin-right: px2rem(-18px);
|
||||||
|
float: right;
|
||||||
|
margin-top: px2rem(2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}Collapse-content {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FieldSet Form + Collapse
|
//FieldSet Form + Collapse
|
||||||
|
@ -64,9 +64,15 @@
|
|||||||
height: #{px2rem(250px)};
|
height: #{px2rem(250px)};
|
||||||
margin-top: #{px2rem(10px)};
|
margin-top: #{px2rem(10px)};
|
||||||
|
|
||||||
& > div {
|
&:not(.is-mobile) > div {
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: scroll;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-settings.only-variable {
|
&-settings.only-variable {
|
||||||
@ -389,6 +395,16 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
&-popup {
|
||||||
|
height: 80vh;
|
||||||
|
|
||||||
|
&-inner {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0 px2rem(16px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-input {
|
&-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-right: #{px2rem(10px)};
|
margin-right: #{px2rem(10px)};
|
||||||
|
@ -72,4 +72,28 @@
|
|||||||
&.is-active &-caret {
|
&.is-active &-caret {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
border: none;
|
||||||
|
border-radius: 0;
|
||||||
|
border-bottom: var(--Form-input-borderWidth) solid
|
||||||
|
var(--Form-input-borderColor);
|
||||||
|
|
||||||
|
&.is-error,
|
||||||
|
.is-error > & {
|
||||||
|
border-bottom-color: var(--Form-input-onError-borderColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-focused {
|
||||||
|
border-bottom-color: var(--Form-input-onFocused-borderColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-error.is-focused {
|
||||||
|
border-bottom-color: var(--Form-input-onError-borderColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
border-bottom-color: var(--Form-input-onDisabled-borderColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,15 @@
|
|||||||
|
|
||||||
color: var(--Form-input-color);
|
color: var(--Form-input-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
& > span {
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
border-bottom: var(--Form-input-borderWidth) solid
|
||||||
|
var(--Form-input-borderColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-value {
|
&-value {
|
||||||
@ -121,4 +130,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
.#{$ns}Number {
|
||||||
|
border-radius: 0;
|
||||||
|
border-bottom: var(--Number-borderWidth) solid
|
||||||
|
var(--Form-input-borderColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,42 @@
|
|||||||
)
|
)
|
||||||
var(--Form-select-paddingX);
|
var(--Form-select-paddingX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.#{$ns}ListMenu-item {
|
||||||
|
width: calc((100vw - var(--ListMenu-item-mobile-margin) * 7) / 3);
|
||||||
|
display: inline-flex;
|
||||||
|
background: var(--ListMenu-item-mobile-bg);
|
||||||
|
margin: var(--ListMenu-item-mobile-margin);
|
||||||
|
|
||||||
|
&.is-active {
|
||||||
|
background: var(--ListMenu-item-mobile-active-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}ListMenu-itemLabel {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}ListMenu-add-wrap {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin: px2rem(20px) 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
input {
|
||||||
|
&::-webkit-input-placeholder {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}PopOver > .#{$ns}ListMenu {
|
.#{$ns}PopOver > .#{$ns}ListMenu {
|
||||||
|
@ -220,7 +220,7 @@
|
|||||||
calc(var(--Panel-marginBottom) / 2);
|
calc(var(--Panel-marginBottom) / 2);
|
||||||
|
|
||||||
.#{$ns}Panel-body {
|
.#{$ns}Panel-body {
|
||||||
padding: 0 var(--gap-md) var(--gap-md);
|
// padding: 0 var(--gap-md) var(--gap-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
> .#{$ns}Panel-heading {
|
> .#{$ns}Panel-heading {
|
||||||
|
@ -132,6 +132,12 @@
|
|||||||
background: var(--SearchBox-enhonce-disabled-color);
|
background: var(--SearchBox-enhonce-disabled-color);
|
||||||
color: var(--SearchBox-enhonce-disabled-search-color);
|
color: var(--SearchBox-enhonce-disabled-search-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
border-bottom: var(--borderWidth) solid var(--borderColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}SearchBox-history {
|
.#{$ns}SearchBox-history {
|
||||||
|
@ -657,6 +657,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
.#{$ns}Table-table > tbody > tr {
|
||||||
|
&:hover,
|
||||||
|
&.is-hovered {
|
||||||
|
background: var(--Table-bg);
|
||||||
|
border-color: var(--Table-borderColor);
|
||||||
|
color: var(--Table-color);
|
||||||
|
|
||||||
|
& + tr {
|
||||||
|
border-color: var(--Table-borderColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&Cell-sortBtn,
|
&Cell-sortBtn,
|
||||||
&Cell-searchBtn,
|
&Cell-searchBtn,
|
||||||
&Cell-filterBtn {
|
&Cell-filterBtn {
|
||||||
|
@ -112,6 +112,18 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
overflow-x: auto;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
overflow: -moz-scrollbars-none;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
width: 0 !important;
|
||||||
|
height: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.#{$ns}Tabs-links-drag {
|
.#{$ns}Tabs-links-drag {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
border-radius: var(--borderRadius);
|
border-radius: var(--borderRadius);
|
||||||
|
|
||||||
&-popup {
|
&-popup {
|
||||||
height: px2rem(400px);
|
height: px2rem(460px);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.is-disabled) {
|
&:not(.is-disabled) {
|
||||||
@ -122,3 +122,26 @@
|
|||||||
border-radius: var(--borderRadius) !important;
|
border-radius: var(--borderRadius) !important;
|
||||||
box-shadow: var(--ColorPicker-boxShadow) !important;
|
box-shadow: var(--ColorPicker-boxShadow) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.#{$ns}ColorPicker-popup {
|
||||||
|
.sketch-picker {
|
||||||
|
width: 80% !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
|
||||||
|
input {
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexbox-fix {
|
||||||
|
&:last-child {
|
||||||
|
> div {
|
||||||
|
width: 18px !important;
|
||||||
|
height: 18px !important;
|
||||||
|
margin: 0px 16px 10px 0px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -320,6 +320,34 @@
|
|||||||
background: rgba(0, 0, 0, 0.1);
|
background: rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
.#{$ns}Form-item {
|
||||||
|
padding: px2rem(10px) 0 0 0;
|
||||||
|
|
||||||
|
.#{$ns}Form-rowInner {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}Combo-delBtn {
|
||||||
|
height: px2rem(20px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-mobile:not(.#{$ns}Combo--ver) {
|
||||||
|
.#{$ns}TextareaControl > textarea,
|
||||||
|
.#{$ns}Form-control > .#{$ns}TextControl-input,
|
||||||
|
.#{$ns}TextControl.is-focused > .#{$ns}TextControl-input {
|
||||||
|
border-bottom: var(--Form-input-borderWidth) solid var(--borderColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-mobile:is(.#{$ns}Combo--hor) {
|
||||||
|
.#{$ns}Form-control {
|
||||||
|
padding-top: px2rem(10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}ComboTabs > .#{$ns}Tabs-links {
|
.#{$ns}ComboTabs > .#{$ns}Tabs-links {
|
||||||
|
@ -185,10 +185,22 @@
|
|||||||
width: auto;
|
width: auto;
|
||||||
// padding-bottom: var(--gap-sm);
|
// padding-bottom: var(--gap-sm);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.#{$ns}DateRangePicker-end {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}DateRangePicker-picker-wrap {
|
.#{$ns}DateRangePicker-picker-wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
&.is-vertical {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}DateRangePicker-start,
|
.#{$ns}DateRangePicker-start,
|
||||||
@ -274,6 +286,10 @@
|
|||||||
border-color: var(--DatePicker-borderColor);
|
border-color: var(--DatePicker-borderColor);
|
||||||
background: var(--DatePicker-bg);
|
background: var(--DatePicker-bg);
|
||||||
border-radius: var(--DatePicker-borderRadius);
|
border-radius: var(--DatePicker-borderRadius);
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移动端输入框样式
|
// 移动端输入框样式
|
||||||
|
@ -456,7 +456,7 @@
|
|||||||
color: var(--inputTime-active-color);
|
color: var(--inputTime-active-color);
|
||||||
background: var(--inputTime-active-bg-color);
|
background: var(--inputTime-active-bg-color);
|
||||||
}
|
}
|
||||||
&:hover {
|
&:not(.is-mobile):hover {
|
||||||
color: var(--inputTime-hover-color);
|
color: var(--inputTime-hover-color);
|
||||||
background: var(--inputTime-hover-bg-color);
|
background: var(--inputTime-hover-bg-color);
|
||||||
}
|
}
|
||||||
@ -466,6 +466,7 @@
|
|||||||
|
|
||||||
.#{$ns}TimeContentWrapper {
|
.#{$ns}TimeContentWrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}TimeRangeHeaderWrapper {
|
.#{$ns}TimeRangeHeaderWrapper {
|
||||||
@ -473,6 +474,7 @@
|
|||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-bottom: 1px solid var(--Calendar-input-borderColor);
|
border-bottom: 1px solid var(--Calendar-input-borderColor);
|
||||||
|
margin: 0 px2rem(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}TimeFooterWrapper {
|
.#{$ns}TimeFooterWrapper {
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
border-left: 0 !important;
|
border-left: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> legend.#{$ns}Collapse-header.is-mobile {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
.collapse {
|
.collapse {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -188,4 +192,13 @@ fieldset.#{$ns}Collapse {
|
|||||||
top: calc(var(--fieldSet-size-lg-fontSize) / 2);
|
top: calc(var(--fieldSet-size-lg-fontSize) / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.#{$ns}Collapse-header.is-mobile {
|
||||||
|
padding-left: var(--gap-xs) !important;
|
||||||
|
padding-right: px2rem(18px);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--white);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,15 +489,21 @@
|
|||||||
/* 移动端样式调整 */
|
/* 移动端样式调整 */
|
||||||
@include media-breakpoint-down(sm) {
|
@include media-breakpoint-down(sm) {
|
||||||
.#{$ns}Form {
|
.#{$ns}Form {
|
||||||
|
// &::before {
|
||||||
|
// position: absolute;
|
||||||
|
// box-sizing: border-box;
|
||||||
|
// content: ' ';
|
||||||
|
// pointer-events: none;
|
||||||
|
// right: 0;
|
||||||
|
// top: 0;
|
||||||
|
// left: 0;
|
||||||
|
// border-bottom: var(--Form-input-borderWidth) solid var(--borderColor);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}Combo-form {
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
border-bottom: none;
|
||||||
box-sizing: border-box;
|
|
||||||
content: ' ';
|
|
||||||
pointer-events: none;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
border-bottom: var(--Form-input-borderWidth) solid var(--borderColor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,6 +618,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
font-size: var(--fontSizeLg);
|
font-size: var(--fontSizeLg);
|
||||||
|
overflow-x: auto;
|
||||||
|
|
||||||
&.is-disabled > .#{$ns}TextControl-input {
|
&.is-disabled > .#{$ns}TextControl-input {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@ -686,6 +693,7 @@
|
|||||||
border: none;
|
border: none;
|
||||||
padding: 0 var(--Form-input-paddingX) 0 0;
|
padding: 0 var(--Form-input-paddingX) 0 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus,
|
&:focus,
|
||||||
@ -716,9 +724,9 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}Divider {
|
// .#{$ns}Divider {
|
||||||
display: none;
|
// display: none;
|
||||||
}
|
// }
|
||||||
|
|
||||||
.#{$ns}Tabs-pane {
|
.#{$ns}Tabs-pane {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -727,4 +735,25 @@
|
|||||||
.#{$ns}Form-item .#{$ns}Form-groupColumn > .#{$ns}Form-item {
|
.#{$ns}Form-item .#{$ns}Form-groupColumn > .#{$ns}Form-item {
|
||||||
padding-bottom: var(--Form-input-paddingX);
|
padding-bottom: var(--Form-input-paddingX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.#{$ns}Form-groupColumn {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
position: absolute;
|
||||||
|
box-sizing: border-box;
|
||||||
|
content: ' ';
|
||||||
|
pointer-events: none;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
border-bottom: var(--Form-input-borderWidth) solid var(--borderColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}Form-groupColumn:nth-last-of-type(1) {
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,12 @@
|
|||||||
.#{$ns}Form-static {
|
.#{$ns}Form-static {
|
||||||
margin-right: var(--gap-xs);
|
margin-right: var(--gap-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
.#{$ns}Form-control {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}InputGroup:not(.is-inline) {
|
.#{$ns}InputGroup:not(.is-inline) {
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
&-placeholder {
|
&-placeholder {
|
||||||
color: var(--colors-neutral-text-6);
|
color: var(--colors-neutral-text-6);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -72,6 +76,27 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-popup {
|
||||||
|
height: px2rem(460px);
|
||||||
|
|
||||||
|
&-inner {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 px2rem(16px);
|
||||||
|
|
||||||
|
.#{$ns}MapPicker-search {
|
||||||
|
padding-top: 0;
|
||||||
|
margin-bottom: px2rem(16px);
|
||||||
|
|
||||||
|
.#{$ns}TextControl-input {
|
||||||
|
border-radius: 0;
|
||||||
|
border-top: none;
|
||||||
|
border-right: none;
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}LocationControl {
|
.#{$ns}LocationControl {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
.#{$ns}MatrixControl {
|
.#{$ns}MatrixControl {
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
&-error {
|
&-error {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,14 @@
|
|||||||
box-shadow: var(--inputNumber-base-active-shadow);
|
box-shadow: var(--inputNumber-base-active-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&-focused {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-disabled {
|
&-disabled {
|
||||||
border-width: var(--inputNumber-base-disabled-top-border-width)
|
border-width: var(--inputNumber-base-disabled-top-border-width)
|
||||||
var(--inputNumber-base-disabled-right-border-width)
|
var(--inputNumber-base-disabled-right-border-width)
|
||||||
|
@ -206,3 +206,15 @@
|
|||||||
min-width: px2rem(150px);
|
min-width: px2rem(150px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.#{$ns}PickerControl.is-mobile {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.#{$ns}Form-item {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}Picker-input {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -33,6 +33,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.#{$ns}InputRange-input {
|
||||||
|
width: var(--InputRange-input-mobile-width);
|
||||||
|
// margin-left: 0;
|
||||||
|
|
||||||
|
.#{$ns}Number-handler-wrap {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 0 !important;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-clear {
|
&-clear {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -97,6 +115,11 @@
|
|||||||
width: var(--InputRange-handle-width);
|
width: var(--InputRange-handle-width);
|
||||||
height: var(--InputRange-handle-height);
|
height: var(--InputRange-handle-height);
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
width: var(--InputRange-handle-mobile-width);
|
||||||
|
height: var(--InputRange-handle-mobile-height);
|
||||||
|
}
|
||||||
|
|
||||||
&-icon,
|
&-icon,
|
||||||
&-drage {
|
&-drage {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -304,4 +327,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
.#{$ns}InputRange-marks {
|
||||||
|
div {
|
||||||
|
top: px2rem(4px);
|
||||||
|
|
||||||
|
&:nth-child(2n) {
|
||||||
|
top: px2rem(-34px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,6 +436,38 @@
|
|||||||
// display: inline-block;
|
// display: inline-block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
& > a {
|
||||||
|
margin-right: calc(
|
||||||
|
20px + var(--select-base-default-option-paddingRight)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}Select-option-item-check {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: px2rem(1px) solid var(--borderColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}Select-option-mcheck {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
right: var(--select-base-default-option-paddingRight);
|
||||||
|
flex: none;
|
||||||
|
width: px2rem(16px);
|
||||||
|
color: var(--Form-select-mobile-icon-check-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
.#{$ns}Select-option-item-check {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-noResult {
|
&-noResult {
|
||||||
|
@ -237,6 +237,16 @@
|
|||||||
color: var(--transfer-search-placeholder-font-color);
|
color: var(--transfer-search-placeholder-font-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
.#{$ns}InputBox {
|
||||||
|
border: none;
|
||||||
|
border-bottom: var(--transfer-search-bottom-border-width)
|
||||||
|
var(--transfer-search-bottom-border-style)
|
||||||
|
var(--transfer-search-bottom-border-color);
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-mid {
|
&-mid {
|
||||||
@ -363,6 +373,25 @@
|
|||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.#{$ns}Transfer-result {
|
||||||
|
.#{$ns}Transfer-title {
|
||||||
|
height: px2rem(40px);
|
||||||
|
line-height: px2rem(40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
.#{$ns}Transfer-search {
|
||||||
|
.#{$ns}InputBox {
|
||||||
|
border: none;
|
||||||
|
border-bottom: var(--transfer-search-bottom-border-width)
|
||||||
|
var(--transfer-search-bottom-border-style)
|
||||||
|
var(--transfer-search-bottom-border-color);
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.#{$ns}TabsTransfer {
|
.#{$ns}TabsTransfer {
|
||||||
@ -463,6 +492,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.#{$ns}TabsTransfer-search {
|
||||||
|
&.is-mobile {
|
||||||
|
.#{$ns}InputBox {
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid var(--TabsTransfer-border-color);
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -528,7 +567,9 @@
|
|||||||
|
|
||||||
&.is-mobile {
|
&.is-mobile {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .#{$ns}Transfer-selection {
|
& > .#{$ns}Transfer-selection {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-height: var(--Transfer-selection-maxHeight);
|
max-height: var(--Transfer-selection-maxHeight);
|
||||||
|
@ -147,9 +147,10 @@
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.#{$ns}Tree {
|
.#{$ns}Tree {
|
||||||
&-itemLabel-item {
|
&-itemLabel-item:not(.is-mobile) {
|
||||||
background-color: var(--Tree-item-onHover-bg-pure);
|
background-color: var(--Tree-item-onHover-bg-pure);
|
||||||
}
|
}
|
||||||
|
|
||||||
&-item-icons {
|
&-item-icons {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
@ -255,6 +256,15 @@
|
|||||||
background: var(--Form-input-onFocused-bg);
|
background: var(--Form-input-onFocused-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-mobile {
|
||||||
|
> input {
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
border-bottom: var(--Form-input-borderWidth) solid
|
||||||
|
var(--Form-input-borderColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-addTopBtn {
|
&-addTopBtn {
|
||||||
@ -398,3 +408,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.#{$ns}PopUp {
|
||||||
|
.#{$ns}Tree {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.#{$ns}Tree-itemLabel {
|
||||||
|
&:hover {
|
||||||
|
.#{$ns}Tree {
|
||||||
|
&-itemLabel-item {
|
||||||
|
background-color: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,14 @@
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
border: 1px solid #f9f9f9;
|
border: 1px solid #f9f9f9;
|
||||||
|
|
||||||
|
&.is-mobile-year {
|
||||||
|
width: px2rem(184px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-mobile-embed {
|
||||||
|
width: px2rem(240px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.rdtPickerNotDays {
|
.rdtPickerNotDays {
|
||||||
|
@ -165,15 +165,17 @@ export class BaiduMapPicker extends React.Component<
|
|||||||
if (poiLength) {
|
if (poiLength) {
|
||||||
for (let i = 0; i < poiLength; i++) {
|
for (let i = 0; i < poiLength; i++) {
|
||||||
const poi = result.getPoi(i);
|
const poi = result.getPoi(i);
|
||||||
sugs.push(
|
if (poi) {
|
||||||
[
|
sugs.push(
|
||||||
poi.province,
|
[
|
||||||
poi.city,
|
poi.province,
|
||||||
poi.district,
|
poi.city,
|
||||||
poi.street,
|
poi.district,
|
||||||
poi.business
|
poi.street,
|
||||||
].join(' ')
|
poi.business
|
||||||
);
|
].join(' ')
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
sugs
|
sugs
|
||||||
@ -288,21 +290,23 @@ export class BaiduMapPicker extends React.Component<
|
|||||||
if (this.props.coordinatesType == 'gcj02') {
|
if (this.props.coordinatesType == 'gcj02') {
|
||||||
this.covertPoint(point, COORDINATES_BD09, COORDINATES_GCJ02).then(
|
this.covertPoint(point, COORDINATES_BD09, COORDINATES_GCJ02).then(
|
||||||
(convertedPoint: any) => {
|
(convertedPoint: any) => {
|
||||||
(typeof this.props?.onChange === 'function') && this.props.onChange({
|
typeof this.props?.onChange === 'function' &&
|
||||||
address: loc.address.trim() || loc.title,
|
this.props.onChange({
|
||||||
lat: convertedPoint.lat,
|
address: loc.address.trim() || loc.title,
|
||||||
lng: convertedPoint.lng,
|
lat: convertedPoint.lat,
|
||||||
city: loc.city
|
lng: convertedPoint.lng,
|
||||||
});
|
city: loc.city
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
(typeof this.props?.onChange === 'function') && this.props?.onChange({
|
typeof this.props?.onChange === 'function' &&
|
||||||
address: loc.address.trim() || loc.title,
|
this.props?.onChange({
|
||||||
lat: loc.lat,
|
address: loc.address.trim() || loc.title,
|
||||||
lng: loc.lng,
|
lat: loc.lat,
|
||||||
city: loc.city
|
lng: loc.lng,
|
||||||
});
|
city: loc.city
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ import {themeable, ThemeProps} from 'amis-core';
|
|||||||
import {LocaleProps, localeable} from 'amis-core';
|
import {LocaleProps, localeable} from 'amis-core';
|
||||||
import {autobind} from 'amis-core';
|
import {autobind} from 'amis-core';
|
||||||
import Button from './Button';
|
import Button from './Button';
|
||||||
|
import {ShortCuts, ShortCutDateRange} from './DatePicker';
|
||||||
|
import {advancedRanges, availableRanges} from './DateRangePicker';
|
||||||
|
import {noop} from 'amis-core';
|
||||||
|
|
||||||
export interface CalendarMobileProps extends ThemeProps, LocaleProps {
|
export interface CalendarMobileProps extends ThemeProps, LocaleProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -49,6 +52,7 @@ export interface CalendarMobileProps extends ThemeProps, LocaleProps {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
defaultDate?: moment.Moment;
|
defaultDate?: moment.Moment;
|
||||||
|
ranges?: string | Array<ShortCuts>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CalendarMobileState {
|
export interface CalendarMobileState {
|
||||||
@ -281,6 +285,97 @@ export class CalendarMobile extends React.Component<
|
|||||||
return dow;
|
return dow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
renderRanges(ranges: string | Array<ShortCuts> | undefined) {
|
||||||
|
if (!ranges) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
classPrefix: ns,
|
||||||
|
embed,
|
||||||
|
minDate,
|
||||||
|
maxDate,
|
||||||
|
confirm,
|
||||||
|
onChange
|
||||||
|
} = this.props;
|
||||||
|
let rangeArr: Array<string | ShortCuts>;
|
||||||
|
if (typeof ranges === 'string') {
|
||||||
|
rangeArr = ranges.split(',');
|
||||||
|
} else {
|
||||||
|
rangeArr = ranges;
|
||||||
|
}
|
||||||
|
const __ = this.props.translate;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className={`${ns}DateRangePicker-rangers`}>
|
||||||
|
{rangeArr.map(item => {
|
||||||
|
if (!item) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let range: any = {};
|
||||||
|
if (typeof item === 'string') {
|
||||||
|
if (availableRanges[item]) {
|
||||||
|
range = availableRanges[item];
|
||||||
|
range.key = item;
|
||||||
|
} else {
|
||||||
|
// 通过正则尝试匹配
|
||||||
|
for (let i = 0, len = advancedRanges.length; i < len; i++) {
|
||||||
|
let value = advancedRanges[i];
|
||||||
|
const m = value.regexp.exec(item);
|
||||||
|
if (m) {
|
||||||
|
range = value.resolve.apply(item, [__, ...m]);
|
||||||
|
range.key = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
(item as ShortCutDateRange).startDate &&
|
||||||
|
(item as ShortCutDateRange).endDate
|
||||||
|
) {
|
||||||
|
range = {
|
||||||
|
...item,
|
||||||
|
startDate: () => (item as ShortCutDateRange).startDate,
|
||||||
|
endDate: () => (item as ShortCutDateRange).endDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (Object.keys(range).length) {
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
className={`${ns}DateRangePicker-ranger`}
|
||||||
|
onClick={() => {
|
||||||
|
const now = moment();
|
||||||
|
const startDate =
|
||||||
|
minDate && minDate.isValid()
|
||||||
|
? moment.max(range.startDate(now.clone()), minDate)
|
||||||
|
: range.startDate(now.clone());
|
||||||
|
const endDate =
|
||||||
|
maxDate && maxDate.isValid()
|
||||||
|
? moment.min(maxDate, range.endDate(now.clone()))
|
||||||
|
: range.endDate(now.clone());
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
startDate,
|
||||||
|
endDate
|
||||||
|
});
|
||||||
|
!embed && onChange && onChange({startDate, endDate}, noop);
|
||||||
|
// 内嵌模式
|
||||||
|
embed &&
|
||||||
|
onChange &&
|
||||||
|
onChange({startDate, endDate}, () => confirm && confirm());
|
||||||
|
}}
|
||||||
|
key={range.key || range.label}
|
||||||
|
>
|
||||||
|
<a>{__(range.label)}</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleCalendarClick(isDisabled: boolean) {
|
handleCalendarClick(isDisabled: boolean) {
|
||||||
if (isDisabled) {
|
if (isDisabled) {
|
||||||
@ -697,7 +792,8 @@ export class CalendarMobile extends React.Component<
|
|||||||
footerExtra,
|
footerExtra,
|
||||||
timeFormat,
|
timeFormat,
|
||||||
showViewMode,
|
showViewMode,
|
||||||
isDatePicker
|
isDatePicker,
|
||||||
|
ranges
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const __ = this.props.translate;
|
const __ = this.props.translate;
|
||||||
|
|
||||||
@ -755,7 +851,7 @@ export class CalendarMobile extends React.Component<
|
|||||||
{timeFormat && startDate && this.renderMobileTimePicker()}
|
{timeFormat && startDate && this.renderMobileTimePicker()}
|
||||||
<div className={cx('CalendarMobile-footer-toolbar')}>
|
<div className={cx('CalendarMobile-footer-toolbar')}>
|
||||||
<div className={cx('CalendarMobile-footer-ranges')}>
|
<div className={cx('CalendarMobile-footer-ranges')}>
|
||||||
{footerExtra}
|
{this.renderRanges(ranges)}
|
||||||
</div>
|
</div>
|
||||||
{confirm && !embed && (
|
{confirm && !embed && (
|
||||||
<Button
|
<Button
|
||||||
|
@ -12,12 +12,15 @@ import compact from 'lodash/compact';
|
|||||||
import find from 'lodash/find';
|
import find from 'lodash/find';
|
||||||
import uniqBy from 'lodash/uniqBy';
|
import uniqBy from 'lodash/uniqBy';
|
||||||
import Button from './Button';
|
import Button from './Button';
|
||||||
|
import Checkbox from './Checkbox';
|
||||||
import {flattenTree, findTree, getTreeDepth} from 'amis-core';
|
import {flattenTree, findTree, getTreeDepth} from 'amis-core';
|
||||||
import type {OptionsControlProps} from 'amis-core';
|
import type {OptionsControlProps} from 'amis-core';
|
||||||
|
import {Icon} from './icons';
|
||||||
|
|
||||||
export type CascaderOption = {
|
export type CascaderOption = {
|
||||||
text?: string;
|
text?: string;
|
||||||
value?: string | number;
|
value?: string | number;
|
||||||
|
valueField?: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
children?: Options;
|
children?: Options;
|
||||||
@ -50,12 +53,12 @@ export type CascaderTab = {
|
|||||||
|
|
||||||
export interface CascaderState {
|
export interface CascaderState {
|
||||||
selectedOptions: Options;
|
selectedOptions: Options;
|
||||||
activeTab: number;
|
|
||||||
tabs: Array<{
|
tabs: Array<{
|
||||||
options: Options;
|
options: Options;
|
||||||
}>;
|
}>;
|
||||||
// 用于在只选择子节点模式的时候禁用按钮
|
// 用于在只选择子节点模式的时候禁用按钮
|
||||||
disableConfirm: boolean;
|
disableConfirm: boolean;
|
||||||
|
activePaths: CascaderOption[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
||||||
@ -68,8 +71,8 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
constructor(props: CascaderProps) {
|
constructor(props: CascaderProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
|
activePaths: [],
|
||||||
selectedOptions: this.props.selectedOptions || [],
|
selectedOptions: this.props.selectedOptions || [],
|
||||||
activeTab: 0,
|
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
options: this.props.options.slice() || []
|
options: this.props.options.slice() || []
|
||||||
@ -109,19 +112,9 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
option.children.forEach((option: Option) => (option.disabled = true));
|
option.children.forEach((option: Option) => (option.disabled = true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return multiple && !onlyLeaf
|
return {
|
||||||
? {
|
options: option.children ? option.children : []
|
||||||
options: [
|
};
|
||||||
{
|
|
||||||
...option,
|
|
||||||
isCheckAll: true
|
|
||||||
},
|
|
||||||
...(option.children ? option.children : [])
|
|
||||||
]
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
options: option.children ? option.children : []
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedOptions,
|
selectedOptions,
|
||||||
@ -129,15 +122,6 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
|
||||||
handleTabSelect(index: number) {
|
|
||||||
const tabs = this.state.tabs.slice(0, index + 1);
|
|
||||||
this.setState({
|
|
||||||
activeTab: index,
|
|
||||||
tabs
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
getOptionParent(option: Option) {
|
getOptionParent(option: Option) {
|
||||||
const {options, valueField = 'value'} = this.props;
|
const {options, valueField = 'value'} = this.props;
|
||||||
@ -202,6 +186,23 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
return loop(selectedOptions);
|
return loop(selectedOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断配置onlyChildren属性时节点选中情况
|
||||||
|
@autobind
|
||||||
|
getOnlyChildrenSelect(option: Option, selectedOptions?: Option[]) {
|
||||||
|
const {onlyChildren} = this.props;
|
||||||
|
selectedOptions = selectedOptions || this.state.selectedOptions;
|
||||||
|
|
||||||
|
return (
|
||||||
|
onlyChildren &&
|
||||||
|
option.children
|
||||||
|
?.filter(option => !option.children?.length)
|
||||||
|
.every(
|
||||||
|
option =>
|
||||||
|
!option.children?.length && selectedOptions?.includes(option)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
getSelectedChildNum(option: Option): number {
|
getSelectedChildNum(option: Option): number {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
@ -267,9 +268,10 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
let index = selectedOptions.findIndex(
|
let index = selectedOptions.findIndex(
|
||||||
(item: Option) => item[valueField] === option[valueField]
|
(item: Option) => item[valueField] === option[valueField]
|
||||||
);
|
);
|
||||||
|
let isSelect = this.getOnlyChildrenSelect(option, selectedOptions);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
selectedOptions.splice(index, 1);
|
selectedOptions.splice(index, 1);
|
||||||
} else {
|
} else if (!isSelect) {
|
||||||
if (!(onlyChildren && option.children?.length)) {
|
if (!(onlyChildren && option.children?.length)) {
|
||||||
selectedOptions.push(option);
|
selectedOptions.push(option);
|
||||||
}
|
}
|
||||||
@ -279,7 +281,7 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
option.children.forEach((item: Option) => {
|
option.children.forEach((item: Option) => {
|
||||||
if (index !== -1) {
|
if (index !== -1 || isSelect) {
|
||||||
// 删除选中节点及其子节点
|
// 删除选中节点及其子节点
|
||||||
selectedOptions = selectedOptions.filter(
|
selectedOptions = selectedOptions.filter(
|
||||||
(sItem: Option) => sItem[valueField] !== item[valueField]
|
(sItem: Option) => sItem[valueField] !== item[valueField]
|
||||||
@ -313,22 +315,27 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
valueField = 'value',
|
valueField = 'value',
|
||||||
cascade,
|
cascade,
|
||||||
onlyLeaf,
|
onlyLeaf,
|
||||||
onlyChildren
|
onlyChildren,
|
||||||
|
withChildren
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let tabs = this.state.tabs.slice();
|
|
||||||
let {activeTab} = this.state;
|
|
||||||
let selectedOptions = this.state.selectedOptions;
|
let selectedOptions = this.state.selectedOptions;
|
||||||
const isDisable = option.disabled;
|
const isDisable = option.disabled;
|
||||||
if (!isDisable) {
|
if (!isDisable) {
|
||||||
if (multiple) {
|
if (multiple) {
|
||||||
// 父子级分离
|
// 父子级分离
|
||||||
if (cascade) {
|
if (cascade) {
|
||||||
if (
|
let index = selectedOptions.findIndex(
|
||||||
option.isCheckAll ||
|
(item: Option) => item[valueField] === option[valueField]
|
||||||
!option.children ||
|
);
|
||||||
!option.children.length
|
if (index !== -1) {
|
||||||
) {
|
selectedOptions.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
selectedOptions.push(option);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (withChildren || onlyChildren) {
|
||||||
|
selectedOptions = this.dealChildrenSelect(option, selectedOptions);
|
||||||
|
} else {
|
||||||
let index = selectedOptions.findIndex(
|
let index = selectedOptions.findIndex(
|
||||||
(item: Option) => item[valueField] === option[valueField]
|
(item: Option) => item[valueField] === option[valueField]
|
||||||
);
|
);
|
||||||
@ -338,29 +345,58 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
selectedOptions.push(option);
|
selectedOptions.push(option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
selectedOptions = this.dealParentSelect(option, selectedOptions);
|
||||||
if (
|
|
||||||
option.isCheckAll ||
|
|
||||||
!option.children ||
|
|
||||||
!option.children.length
|
|
||||||
) {
|
|
||||||
selectedOptions = this.dealChildrenSelect(option, selectedOptions);
|
|
||||||
if (!onlyChildren) {
|
|
||||||
selectedOptions = this.dealParentSelect(option, selectedOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 单选
|
// 单选
|
||||||
selectedOptions = [option];
|
if (onlyLeaf) {
|
||||||
|
if (!option.children?.length) {
|
||||||
|
selectedOptions = [option];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selectedOptions = [option];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.dealOptionDisable(selectedOptions);
|
this.dealOptionDisable(selectedOptions);
|
||||||
|
|
||||||
|
let disableConfirm = false;
|
||||||
|
if (onlyLeaf && selectedOptions.length && selectedOptions[0].children) {
|
||||||
|
disableConfirm = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
selectedOptions,
|
||||||
|
disableConfirm
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleExpand(option: Option, tabIndex: number) {
|
||||||
|
const activePaths = this.state.activePaths.slice();
|
||||||
|
|
||||||
|
if (option.children?.length) {
|
||||||
|
activePaths[tabIndex] = option;
|
||||||
|
} else {
|
||||||
|
activePaths.splice(tabIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tabs = this.state.tabs.slice();
|
||||||
if (tabs.length > tabIndex + 1) {
|
if (tabs.length > tabIndex + 1) {
|
||||||
tabs = tabs.slice(0, tabIndex + 1);
|
tabs = tabs.slice(0, tabIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (option?.children) {
|
||||||
|
const nextTab = {
|
||||||
|
options: option.children
|
||||||
|
};
|
||||||
|
if (tabs[tabIndex + 1]) {
|
||||||
|
tabs[tabIndex + 1] = nextTab;
|
||||||
|
} else {
|
||||||
|
tabs.push(nextTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const tabWidth = this.tabRef.current?.offsetWidth || 1;
|
const tabWidth = this.tabRef.current?.offsetWidth || 1;
|
||||||
const parentTree = this.getParentTree(option, [option]);
|
const parentTree = this.getParentTree(option, [option]);
|
||||||
@ -370,60 +406,9 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (option?.children && !option.isCheckAll) {
|
|
||||||
const nextTab =
|
|
||||||
multiple && !onlyLeaf
|
|
||||||
? {
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
...option,
|
|
||||||
isCheckAll: true
|
|
||||||
},
|
|
||||||
...option.children
|
|
||||||
]
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
options: option.children
|
|
||||||
};
|
|
||||||
|
|
||||||
if (tabs[tabIndex + 1]) {
|
|
||||||
tabs[tabIndex + 1] = nextTab;
|
|
||||||
} else {
|
|
||||||
tabs.push(nextTab);
|
|
||||||
}
|
|
||||||
activeTab += 1;
|
|
||||||
}
|
|
||||||
let disableConfirm = false;
|
|
||||||
if (onlyLeaf && selectedOptions.length && selectedOptions[0].children) {
|
|
||||||
disableConfirm = true;
|
|
||||||
}
|
|
||||||
this.setState({
|
this.setState({
|
||||||
tabs,
|
activePaths,
|
||||||
activeTab,
|
tabs
|
||||||
selectedOptions,
|
|
||||||
disableConfirm
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@autobind
|
|
||||||
onNextClick(option: CascaderOption, tabIndex: number) {
|
|
||||||
let {activeTab} = this.state;
|
|
||||||
let tabs = this.state.tabs.slice();
|
|
||||||
if (option.c)
|
|
||||||
if (option?.children) {
|
|
||||||
const nextTab = {
|
|
||||||
options: option.children
|
|
||||||
};
|
|
||||||
if (tabs[tabIndex + 1]) {
|
|
||||||
tabs[tabIndex + 1] = nextTab;
|
|
||||||
} else {
|
|
||||||
tabs.push(nextTab);
|
|
||||||
}
|
|
||||||
activeTab += 1;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
tabs,
|
|
||||||
activeTab
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,15 +447,7 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
confirm() {
|
confirm() {
|
||||||
const {
|
const {onChange, onClose, onlyLeaf} = this.props;
|
||||||
onChange,
|
|
||||||
joinValues,
|
|
||||||
delimiter,
|
|
||||||
extractValue,
|
|
||||||
valueField,
|
|
||||||
onClose,
|
|
||||||
onlyLeaf
|
|
||||||
} = this.props;
|
|
||||||
const selectedOptions = this.getSelectedOptions();
|
const selectedOptions = this.getSelectedOptions();
|
||||||
if (onlyLeaf && selectedOptions.length && selectedOptions[0].children) {
|
if (onlyLeaf && selectedOptions.length && selectedOptions[0].children) {
|
||||||
return;
|
return;
|
||||||
@ -490,15 +467,15 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
@autobind
|
@autobind
|
||||||
renderOption(option: CascaderOption, tabIndex: number) {
|
renderOption(option: CascaderOption, tabIndex: number) {
|
||||||
const {
|
const {
|
||||||
|
onlyLeaf,
|
||||||
activeColor,
|
activeColor,
|
||||||
optionRender,
|
optionRender,
|
||||||
labelField,
|
labelField,
|
||||||
valueField = 'value',
|
valueField = 'value',
|
||||||
classnames: cx,
|
multiple,
|
||||||
cascade,
|
classnames: cx
|
||||||
multiple
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {selectedOptions} = this.state;
|
const {selectedOptions, activePaths} = this.state;
|
||||||
const selectedValueArr = selectedOptions.map(item => item[valueField]);
|
const selectedValueArr = selectedOptions.map(item => item[valueField]);
|
||||||
|
|
||||||
let selfChecked = selectedValueArr.includes(option[valueField]);
|
let selfChecked = selectedValueArr.includes(option[valueField]);
|
||||||
@ -508,21 +485,51 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
) : (
|
) : (
|
||||||
<span>{option[labelField]}</span>
|
<span>{option[labelField]}</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className={cx(
|
className={cx(
|
||||||
'Cascader-option',
|
'Cascader-option',
|
||||||
{
|
{
|
||||||
selected: selfChecked,
|
'selected': selfChecked,
|
||||||
disabled: option.disabled
|
'disabled': option.disabled,
|
||||||
|
'is-active': activePaths.includes(option)
|
||||||
},
|
},
|
||||||
option.className
|
option.className
|
||||||
)}
|
)}
|
||||||
style={{color}}
|
style={{color}}
|
||||||
onClick={() => this.onSelect(option, tabIndex)}
|
|
||||||
key={tabIndex + '-' + option[valueField]}
|
key={tabIndex + '-' + option[valueField]}
|
||||||
|
onClick={() => {
|
||||||
|
!multiple && this.onSelect(option, tabIndex);
|
||||||
|
this.handleExpand(option, tabIndex);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<span className={cx('Cascader-option--text')}>{Text}</span>
|
{multiple ? (
|
||||||
|
<Checkbox
|
||||||
|
disabled={option.disabled || (onlyLeaf && option.children?.length)}
|
||||||
|
checked={
|
||||||
|
selectedOptions.includes(option) ||
|
||||||
|
this.getOnlyChildrenSelect(option)
|
||||||
|
}
|
||||||
|
onChange={() => this.onSelect(option, tabIndex)}
|
||||||
|
>
|
||||||
|
<span className={cx('Cascader-option--text')}>{Text}</span>
|
||||||
|
</Checkbox>
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
className={cx('Cascader-option--text', {
|
||||||
|
disabled: onlyLeaf && option.children?.length
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{Text}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{option.children?.length ? (
|
||||||
|
<span className={cx('Cascader-option-arrow')}>
|
||||||
|
<Icon icon="right-arrow-bold" className="icon" />
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -551,7 +558,7 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
const {options} = tab;
|
const {options} = tab;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(`Cascader-tab`)}
|
className={cx(`Cascader-tab depth-${tabIndex}`)}
|
||||||
ref={this.tabRef}
|
ref={this.tabRef}
|
||||||
key={tabIndex}
|
key={tabIndex}
|
||||||
>
|
>
|
||||||
@ -563,7 +570,10 @@ export class Cascader extends React.Component<CascaderProps, CascaderState> {
|
|||||||
? Array(getTreeDepth(options) - tabs.length)
|
? Array(getTreeDepth(options) - tabs.length)
|
||||||
.fill(1)
|
.fill(1)
|
||||||
.map((item: number, index: number) => (
|
.map((item: number, index: number) => (
|
||||||
<div className={cx(`Cascader-tab`)} key={index}></div>
|
<div
|
||||||
|
className={cx(`Cascader-tab depth-${index + 1}`)}
|
||||||
|
key={index}
|
||||||
|
></div>
|
||||||
))
|
))
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,6 +14,7 @@ import Transition, {
|
|||||||
import {autobind} from 'amis-core';
|
import {autobind} from 'amis-core';
|
||||||
import {isClickOnInput} from 'amis-core';
|
import {isClickOnInput} from 'amis-core';
|
||||||
import {TranslateFn} from 'amis-core';
|
import {TranslateFn} from 'amis-core';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
import {Icon} from './icons';
|
import {Icon} from './icons';
|
||||||
|
|
||||||
const collapseStyles: {
|
const collapseStyles: {
|
||||||
@ -54,6 +55,7 @@ export interface CollapseProps {
|
|||||||
propsUpdate?: boolean;
|
propsUpdate?: boolean;
|
||||||
partial?: boolean;
|
partial?: boolean;
|
||||||
children?: React.ReactNode | Array<React.ReactNode>;
|
children?: React.ReactNode | Array<React.ReactNode>;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CollapseState {
|
export interface CollapseState {
|
||||||
@ -170,19 +172,25 @@ export class Collapse extends React.Component<CollapseProps, CollapseState> {
|
|||||||
showArrow,
|
showArrow,
|
||||||
expandIcon,
|
expandIcon,
|
||||||
disabled,
|
disabled,
|
||||||
children
|
children,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const finalHeader = this.state.collapsed
|
const finalHeader = this.state.collapsed
|
||||||
? header
|
? header
|
||||||
: collapseHeader || header;
|
: collapseHeader || header;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
let dom = [
|
let dom = [
|
||||||
finalHeader ? (
|
finalHeader ? (
|
||||||
<HeadingComponent
|
<HeadingComponent
|
||||||
key="header"
|
key="header"
|
||||||
onClick={this.toggleCollapsed}
|
onClick={this.toggleCollapsed}
|
||||||
className={cx(`Collapse-header`, headingClassName)}
|
className={cx(
|
||||||
|
`Collapse-header`,
|
||||||
|
{'is-mobile': mobileUI},
|
||||||
|
headingClassName
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{showArrow && collapsable ? (
|
{showArrow && collapsable ? (
|
||||||
expandIcon ? (
|
expandIcon ? (
|
||||||
@ -249,6 +257,7 @@ export class Collapse extends React.Component<CollapseProps, CollapseState> {
|
|||||||
className={cx(
|
className={cx(
|
||||||
`Collapse`,
|
`Collapse`,
|
||||||
{
|
{
|
||||||
|
'is-mobile': mobileUI,
|
||||||
'is-active': !this.state.collapsed,
|
'is-active': !this.state.collapsed,
|
||||||
[`Collapse--${size}`]: size,
|
[`Collapse--${size}`]: size,
|
||||||
'Collapse--disabled': disabled,
|
'Collapse--disabled': disabled,
|
||||||
|
@ -13,6 +13,7 @@ export interface CollapseItem {
|
|||||||
|
|
||||||
import {ClassNamesFn, themeable, autobind} from 'amis-core';
|
import {ClassNamesFn, themeable, autobind} from 'amis-core';
|
||||||
import type {SchemaNode} from 'amis-core';
|
import type {SchemaNode} from 'amis-core';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
|
|
||||||
export interface CollapseGroupProps {
|
export interface CollapseGroupProps {
|
||||||
@ -26,6 +27,7 @@ export interface CollapseGroupProps {
|
|||||||
classnames: ClassNamesFn;
|
classnames: ClassNamesFn;
|
||||||
classPrefix: string;
|
classPrefix: string;
|
||||||
children?: React.ReactNode | Array<React.ReactNode>;
|
children?: React.ReactNode | Array<React.ReactNode>;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CollapseGroupState {
|
export interface CollapseGroupState {
|
||||||
@ -136,8 +138,10 @@ class CollapseGroup extends React.Component<
|
|||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
expandIconPosition,
|
expandIconPosition,
|
||||||
children
|
children,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -146,6 +150,9 @@ class CollapseGroup extends React.Component<
|
|||||||
{
|
{
|
||||||
'icon-position-right': expandIconPosition === 'right'
|
'icon-position-right': expandIconPosition === 'right'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
},
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
style={style}
|
style={style}
|
||||||
|
@ -40,6 +40,7 @@ export interface ColorControlState {
|
|||||||
isOpened: boolean;
|
isOpened: boolean;
|
||||||
isFocused: boolean;
|
isFocused: boolean;
|
||||||
inputValue: string;
|
inputValue: string;
|
||||||
|
tempValue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ColorControl extends React.PureComponent<
|
export class ColorControl extends React.PureComponent<
|
||||||
@ -56,7 +57,8 @@ export class ColorControl extends React.PureComponent<
|
|||||||
state = {
|
state = {
|
||||||
isOpened: false,
|
isOpened: false,
|
||||||
isFocused: false,
|
isFocused: false,
|
||||||
inputValue: this.props.value || ''
|
inputValue: this.props.value || '',
|
||||||
|
tempValue: this.props.value || ''
|
||||||
};
|
};
|
||||||
popover: any;
|
popover: any;
|
||||||
closeTimer: number;
|
closeTimer: number;
|
||||||
@ -70,6 +72,8 @@ export class ColorControl extends React.PureComponent<
|
|||||||
this.focus = this.focus.bind(this);
|
this.focus = this.focus.bind(this);
|
||||||
this.blur = this.blur.bind(this);
|
this.blur = this.blur.bind(this);
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
|
this.handleTempChange = this.handleTempChange.bind(this);
|
||||||
|
this.handleConfirm = this.handleConfirm.bind(this);
|
||||||
this.handleFocus = this.handleFocus.bind(this);
|
this.handleFocus = this.handleFocus.bind(this);
|
||||||
this.handleBlur = this.handleBlur.bind(this);
|
this.handleBlur = this.handleBlur.bind(this);
|
||||||
this.clearValue = this.clearValue.bind(this);
|
this.clearValue = this.clearValue.bind(this);
|
||||||
@ -206,6 +210,31 @@ export class ColorControl extends React.PureComponent<
|
|||||||
// closeOnSelect && this.close();
|
// closeOnSelect && this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleTempChange(color: ColorResult) {
|
||||||
|
let {tempValue} = this.state;
|
||||||
|
const {format} = this.props;
|
||||||
|
|
||||||
|
if (format === 'rgba') {
|
||||||
|
tempValue = `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`;
|
||||||
|
} else if (format === 'rgb') {
|
||||||
|
tempValue = `rgb(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b})`;
|
||||||
|
} else if (format === 'hsl') {
|
||||||
|
tempValue = `hsl(${Math.round(color.hsl.h)}, ${Math.round(
|
||||||
|
color.hsl.s * 100
|
||||||
|
)}%, ${Math.round(color.hsl.l * 100)}%)`;
|
||||||
|
} else {
|
||||||
|
tempValue = color.hex;
|
||||||
|
}
|
||||||
|
this.setState({tempValue});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleConfirm() {
|
||||||
|
const {onChange} = this.props;
|
||||||
|
const {tempValue} = this.state;
|
||||||
|
onChange(tempValue);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
classPrefix: ns,
|
classPrefix: ns,
|
||||||
@ -227,6 +256,7 @@ export class ColorControl extends React.PureComponent<
|
|||||||
const __ = this.props.translate;
|
const __ = this.props.translate;
|
||||||
const isOpened = this.state.isOpened;
|
const isOpened = this.state.isOpened;
|
||||||
const isFocused = this.state.isFocused;
|
const isFocused = this.state.isFocused;
|
||||||
|
const tempValue = this.state.tempValue;
|
||||||
const mobileUI = useMobileUI && isMobile();
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -328,18 +358,20 @@ export class ColorControl extends React.PureComponent<
|
|||||||
container={popOverContainer}
|
container={popOverContainer}
|
||||||
isShow={isOpened}
|
isShow={isOpened}
|
||||||
onHide={this.handleClick}
|
onHide={this.handleClick}
|
||||||
|
showConfirm
|
||||||
|
onConfirm={this.handleConfirm}
|
||||||
>
|
>
|
||||||
{allowCustomColor ? (
|
{allowCustomColor ? (
|
||||||
<SketchPicker
|
<SketchPicker
|
||||||
styles={{}}
|
styles={{}}
|
||||||
disableAlpha={!!~['rgb', 'hex'].indexOf(format as string)}
|
disableAlpha={!!~['rgb', 'hex'].indexOf(format as string)}
|
||||||
color={value}
|
color={tempValue}
|
||||||
presetColors={presetColors}
|
presetColors={presetColors}
|
||||||
onChangeComplete={this.handleChange}
|
onChangeComplete={this.handleTempChange}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<GithubPicker
|
<GithubPicker
|
||||||
color={value}
|
color={tempValue}
|
||||||
colors={
|
colors={
|
||||||
Array.isArray(presetColors)
|
Array.isArray(presetColors)
|
||||||
? (presetColors
|
? (presetColors
|
||||||
@ -355,7 +387,7 @@ export class ColorControl extends React.PureComponent<
|
|||||||
) as string[])
|
) as string[])
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
onChangeComplete={this.handleChange}
|
onChangeComplete={this.handleTempChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</PopUp>
|
</PopUp>
|
||||||
|
@ -2,8 +2,15 @@ import React from 'react';
|
|||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import Button from './Button';
|
import Button from './Button';
|
||||||
import Drawer from './Drawer';
|
import Drawer from './Drawer';
|
||||||
import {localeable, LocaleProps, themeable, ThemeProps} from 'amis-core';
|
import {
|
||||||
|
localeable,
|
||||||
|
LocaleProps,
|
||||||
|
themeable,
|
||||||
|
ThemeProps,
|
||||||
|
isMobile
|
||||||
|
} from 'amis-core';
|
||||||
import Spinner from './Spinner';
|
import Spinner from './Spinner';
|
||||||
|
import PopUp from './PopUp';
|
||||||
|
|
||||||
export interface ConfirmBoxProps extends LocaleProps, ThemeProps {
|
export interface ConfirmBoxProps extends LocaleProps, ThemeProps {
|
||||||
show?: boolean;
|
show?: boolean;
|
||||||
@ -34,6 +41,7 @@ export interface ConfirmBoxProps extends LocaleProps, ThemeProps {
|
|||||||
headerClassName?: string;
|
headerClassName?: string;
|
||||||
bodyClassName?: string;
|
bodyClassName?: string;
|
||||||
footerClassName?: string;
|
footerClassName?: string;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ConfirmBox({
|
export function ConfirmBox({
|
||||||
@ -56,7 +64,8 @@ export function ConfirmBox({
|
|||||||
classnames: cx,
|
classnames: cx,
|
||||||
className,
|
className,
|
||||||
bodyClassName,
|
bodyClassName,
|
||||||
footerClassName
|
footerClassName,
|
||||||
|
useMobileUI
|
||||||
}: ConfirmBoxProps) {
|
}: ConfirmBoxProps) {
|
||||||
const [loading, setLoading] = React.useState<boolean>();
|
const [loading, setLoading] = React.useState<boolean>();
|
||||||
const [error, setError] = React.useState<string>();
|
const [error, setError] = React.useState<string>();
|
||||||
@ -90,7 +99,22 @@ export function ConfirmBox({
|
|||||||
}, [show]);
|
}, [show]);
|
||||||
|
|
||||||
function renderDialog() {
|
function renderDialog() {
|
||||||
return (
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
return mobileUI ? (
|
||||||
|
<PopUp
|
||||||
|
isShow={show}
|
||||||
|
showConfirm
|
||||||
|
onConfirm={handleConfirm}
|
||||||
|
onHide={onCancel}
|
||||||
|
>
|
||||||
|
{typeof children === 'function'
|
||||||
|
? children({
|
||||||
|
bodyRef: bodyRef,
|
||||||
|
loading
|
||||||
|
})
|
||||||
|
: children}
|
||||||
|
</PopUp>
|
||||||
|
) : (
|
||||||
<Modal
|
<Modal
|
||||||
size={size}
|
size={size}
|
||||||
closeOnEsc={closeOnEsc}
|
closeOnEsc={closeOnEsc}
|
||||||
|
@ -1035,7 +1035,9 @@ export class DateRangePicker extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectShortcut(shortcut: PlainObject) {
|
selectShortcut(shortcut: PlainObject) {
|
||||||
const {closeOnSelect, minDateRaw, maxDateRaw, format, data} = this.props;
|
const {closeOnSelect, minDateRaw, maxDateRaw, format, data, useMobileUI} =
|
||||||
|
this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
const now = moment();
|
const now = moment();
|
||||||
/** minDate和maxDate要实时计算,因为用户可能设置为${NOW()},暂时不考虑毫秒级的时间差 */
|
/** minDate和maxDate要实时计算,因为用户可能设置为${NOW()},暂时不考虑毫秒级的时间差 */
|
||||||
const minDate = minDateRaw
|
const minDate = minDateRaw
|
||||||
@ -1056,7 +1058,7 @@ export class DateRangePicker extends React.Component<
|
|||||||
endDate:
|
endDate:
|
||||||
maxDate && maxDate?.isValid() ? moment.min(maxDate, endDate) : endDate
|
maxDate && maxDate?.isValid() ? moment.min(maxDate, endDate) : endDate
|
||||||
},
|
},
|
||||||
closeOnSelect ? this.confirm : noop
|
closeOnSelect && !mobileUI ? this.confirm : noop
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1382,7 +1384,9 @@ export class DateRangePicker extends React.Component<
|
|||||||
locale,
|
locale,
|
||||||
embed,
|
embed,
|
||||||
type,
|
type,
|
||||||
viewMode = 'days'
|
viewMode = 'days',
|
||||||
|
label,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const __ = this.props.translate;
|
const __ = this.props.translate;
|
||||||
const {startDate, endDate, editState} = this.state;
|
const {startDate, endDate, editState} = this.state;
|
||||||
@ -1400,12 +1404,48 @@ export class DateRangePicker extends React.Component<
|
|||||||
!endDate ||
|
!endDate ||
|
||||||
!startDate?.isValid() ||
|
!startDate?.isValid() ||
|
||||||
!endDate?.isValid()));
|
!endDate?.isValid()));
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx(`${ns}DateRangePicker-wrap`)} ref={this.calendarRef}>
|
<div
|
||||||
|
className={cx(`${ns}DateRangePicker-wrap`, {'is-mobile': mobileUI})}
|
||||||
|
ref={this.calendarRef}
|
||||||
|
>
|
||||||
{this.renderShortcuts(shortcuts ?? ranges)}
|
{this.renderShortcuts(shortcuts ?? ranges)}
|
||||||
<div className={cx(`${ns}DateRangePicker-picker-wrap`)}>
|
{mobileUI && !embed ? (
|
||||||
{(!isTimeRange || (editState === 'start' && !embed)) && (
|
<div className={cx('PickerColumns-header')}>
|
||||||
|
{
|
||||||
|
<Button
|
||||||
|
className="PickerColumns-cancel"
|
||||||
|
level="link"
|
||||||
|
onClick={() => this.close(false)}
|
||||||
|
>
|
||||||
|
{__('cancel')}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
{label && typeof label === 'string'
|
||||||
|
? label
|
||||||
|
: __('Calendar.datepicker')}
|
||||||
|
{
|
||||||
|
<Button
|
||||||
|
className="PickerColumns-confirm"
|
||||||
|
level="link"
|
||||||
|
disabled={isConfirmBtnDisbaled || !startDate || !endDate}
|
||||||
|
onClick={this.confirm}
|
||||||
|
>
|
||||||
|
{__('confirm')}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<div
|
||||||
|
className={cx(`${ns}DateRangePicker-picker-wrap`, {
|
||||||
|
'is-vertical': embed
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{(!isTimeRange ||
|
||||||
|
(editState === 'start' && !embed) ||
|
||||||
|
(mobileUI && isTimeRange)) && (
|
||||||
<Calendar
|
<Calendar
|
||||||
className={`${ns}DateRangePicker-start`}
|
className={`${ns}DateRangePicker-start`}
|
||||||
value={startDate}
|
value={startDate}
|
||||||
@ -1432,9 +1472,12 @@ export class DateRangePicker extends React.Component<
|
|||||||
renderYear={this.renderYear}
|
renderYear={this.renderYear}
|
||||||
locale={locale}
|
locale={locale}
|
||||||
timeRangeHeader="开始时间"
|
timeRangeHeader="开始时间"
|
||||||
|
embed={embed}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{(!isTimeRange || (editState === 'end' && !embed)) && (
|
{(!isTimeRange ||
|
||||||
|
(editState === 'end' && !embed) ||
|
||||||
|
(mobileUI && isTimeRange)) && (
|
||||||
<Calendar
|
<Calendar
|
||||||
className={`${ns}DateRangePicker-end`}
|
className={`${ns}DateRangePicker-end`}
|
||||||
value={endDate}
|
value={endDate}
|
||||||
@ -1461,11 +1504,12 @@ export class DateRangePicker extends React.Component<
|
|||||||
renderYear={this.renderYear}
|
renderYear={this.renderYear}
|
||||||
locale={locale}
|
locale={locale}
|
||||||
timeRangeHeader="结束时间"
|
timeRangeHeader="结束时间"
|
||||||
|
embed={embed}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{embed ? null : (
|
{embed || mobileUI ? null : (
|
||||||
<div key="button" className={`${ns}DateRangePicker-actions`}>
|
<div key="button" className={`${ns}DateRangePicker-actions`}>
|
||||||
{/* this.close 这里不可以传参 */}
|
{/* this.close 这里不可以传参 */}
|
||||||
<Button size="sm" onClick={() => this.close()}>
|
<Button size="sm" onClick={() => this.close()}>
|
||||||
@ -1631,11 +1675,16 @@ export class DateRangePicker extends React.Component<
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
if (embed) {
|
if (embed) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
`${ns}DateRangeCalendar`,
|
`${ns}DateRangeCalendar`,
|
||||||
|
{
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'is-disabled': disabled
|
'is-disabled': disabled
|
||||||
},
|
},
|
||||||
@ -1739,7 +1788,8 @@ export class DateRangePicker extends React.Component<
|
|||||||
`${ns}CalendarMobile-pop--${viewMode}`
|
`${ns}CalendarMobile-pop--${viewMode}`
|
||||||
)}
|
)}
|
||||||
onHide={this.close}
|
onHide={this.close}
|
||||||
header={CalendarMobileTitle}
|
showClose={false}
|
||||||
|
// header={CalendarMobileTitle}
|
||||||
>
|
>
|
||||||
{useCalendarMobile ? calendarMobile : this.renderCalendar()}
|
{useCalendarMobile ? calendarMobile : this.renderCalendar()}
|
||||||
</PopUp>
|
</PopUp>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {ThemeProps, themeable} from 'amis-core';
|
import {ThemeProps, themeable, isMobile} from 'amis-core';
|
||||||
import Input from './Input';
|
import Input from './Input';
|
||||||
import {autobind, ucFirst} from 'amis-core';
|
import {autobind, ucFirst} from 'amis-core';
|
||||||
import {Icon} from './icons';
|
import {Icon} from './icons';
|
||||||
@ -18,6 +18,7 @@ export interface InputBoxProps
|
|||||||
prefix?: JSX.Element;
|
prefix?: JSX.Element;
|
||||||
children?: React.ReactNode | Array<React.ReactNode>;
|
children?: React.ReactNode | Array<React.ReactNode>;
|
||||||
borderMode?: 'full' | 'half' | 'none';
|
borderMode?: 'full' | 'half' | 'none';
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InputBoxState {
|
export interface InputBoxState {
|
||||||
@ -83,13 +84,16 @@ export class InputBox extends React.Component<InputBoxProps, InputBoxState> {
|
|||||||
children,
|
children,
|
||||||
borderMode,
|
borderMode,
|
||||||
onClick,
|
onClick,
|
||||||
|
useMobileUI,
|
||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const isFocused = this.state.isFocused;
|
const isFocused = this.state.isFocused;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx('InputBox', className, {
|
className={cx('InputBox', className, {
|
||||||
|
'is-mobile': mobileUI,
|
||||||
'is-focused': isFocused,
|
'is-focused': isFocused,
|
||||||
'is-disabled': disabled,
|
'is-disabled': disabled,
|
||||||
'is-error': hasError,
|
'is-error': hasError,
|
||||||
|
@ -20,6 +20,7 @@ export interface InputBoxWithSuggestionProps extends ThemeProps, LocaleProps {
|
|||||||
hasError?: boolean;
|
hasError?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
clearable?: boolean;
|
clearable?: boolean;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const option2value = (item: any) => item.value;
|
const option2value = (item: any) => item.value;
|
||||||
@ -65,7 +66,8 @@ export class InputBoxWithSuggestion extends React.Component<InputBoxWithSuggesti
|
|||||||
searchable,
|
searchable,
|
||||||
popOverContainer,
|
popOverContainer,
|
||||||
clearable,
|
clearable,
|
||||||
hasError
|
hasError,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const options = this.filterOptions(
|
const options = this.filterOptions(
|
||||||
Array.isArray(this.props.options) ? this.props.options : []
|
Array.isArray(this.props.options) ? this.props.options : []
|
||||||
@ -103,6 +105,7 @@ export class InputBoxWithSuggestion extends React.Component<InputBoxWithSuggesti
|
|||||||
clearable={clearable}
|
clearable={clearable}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
hasError={hasError}
|
hasError={hasError}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
>
|
>
|
||||||
<span className={cx('InputBox-caret')}>
|
<span className={cx('InputBox-caret')}>
|
||||||
<Icon icon="caret" className="icon" />
|
<Icon icon="caret" className="icon" />
|
||||||
|
@ -161,7 +161,7 @@ export function InputTable({
|
|||||||
|
|
||||||
function renderBody() {
|
function renderBody() {
|
||||||
return (
|
return (
|
||||||
<div className={cx(`Table`, className)}>
|
<div className={cx(`Table`)}>
|
||||||
<div className={cx(`Table-contentWrap`)}>
|
<div className={cx(`Table-contentWrap`)}>
|
||||||
<table className={cx(`Table-table`)}>
|
<table className={cx(`Table-table`)}>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -2,6 +2,7 @@ import {ThemeProps, themeable} from 'amis-core';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Options, Option} from 'amis-core';
|
import {Options, Option} from 'amis-core';
|
||||||
import {LocaleProps, localeable} from 'amis-core';
|
import {LocaleProps, localeable} from 'amis-core';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
export interface ListMenuProps extends ThemeProps, LocaleProps {
|
export interface ListMenuProps extends ThemeProps, LocaleProps {
|
||||||
options: Options;
|
options: Options;
|
||||||
@ -14,6 +15,7 @@ export interface ListMenuProps extends ThemeProps, LocaleProps {
|
|||||||
getItemProps: (props: {item: Option; index: number}) => any;
|
getItemProps: (props: {item: Option; index: number}) => any;
|
||||||
prefix?: JSX.Element;
|
prefix?: JSX.Element;
|
||||||
children?: React.ReactNode | Array<React.ReactNode>;
|
children?: React.ReactNode | Array<React.ReactNode>;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RenderResult {
|
interface RenderResult {
|
||||||
@ -36,6 +38,7 @@ export class ListMenu extends React.Component<ListMenuProps> {
|
|||||||
getItemProps,
|
getItemProps,
|
||||||
highlightIndex,
|
highlightIndex,
|
||||||
selectedOptions,
|
selectedOptions,
|
||||||
|
useMobileUI,
|
||||||
onSelect
|
onSelect
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@ -86,11 +89,20 @@ export class ListMenu extends React.Component<ListMenuProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {classnames: cx, options, placeholder, prefix, children} = this.props;
|
const {
|
||||||
|
classnames: cx,
|
||||||
|
options,
|
||||||
|
placeholder,
|
||||||
|
prefix,
|
||||||
|
children,
|
||||||
|
useMobileUI,
|
||||||
|
selectedOptions
|
||||||
|
} = this.props;
|
||||||
const __ = this.props.translate;
|
const __ = this.props.translate;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx('ListMenu')}>
|
<div className={cx('ListMenu', {'is-mobile': mobileUI})}>
|
||||||
{prefix}
|
{prefix}
|
||||||
{Array.isArray(options) && options.length ? (
|
{Array.isArray(options) && options.length ? (
|
||||||
options.reduce(
|
options.reduce(
|
||||||
|
@ -8,6 +8,8 @@ import Alert2 from './Alert2';
|
|||||||
import BaiduMapPicker from './BaiduMapPicker';
|
import BaiduMapPicker from './BaiduMapPicker';
|
||||||
import GaodeMapPicker from './GaodeMapPicker';
|
import GaodeMapPicker from './GaodeMapPicker';
|
||||||
import {LocaleProps, localeable} from 'amis-core';
|
import {LocaleProps, localeable} from 'amis-core';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
import PopUp from './PopUp';
|
||||||
|
|
||||||
export interface LocationProps extends ThemeProps, LocaleProps {
|
export interface LocationProps extends ThemeProps, LocaleProps {
|
||||||
vendor: 'baidu' | 'gaode' | 'tenxun';
|
vendor: 'baidu' | 'gaode' | 'tenxun';
|
||||||
@ -26,6 +28,7 @@ export interface LocationProps extends ThemeProps, LocaleProps {
|
|||||||
popoverClassName?: string;
|
popoverClassName?: string;
|
||||||
onChange: (value: any) => void;
|
onChange: (value: any) => void;
|
||||||
popOverContainer?: any;
|
popOverContainer?: any;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LocationState {
|
export interface LocationState {
|
||||||
@ -42,6 +45,7 @@ export class LocationPicker extends React.Component<
|
|||||||
clearable: false
|
clearable: false
|
||||||
};
|
};
|
||||||
domRef: React.RefObject<HTMLDivElement> = React.createRef();
|
domRef: React.RefObject<HTMLDivElement> = React.createRef();
|
||||||
|
tempValue: any;
|
||||||
state = {
|
state = {
|
||||||
isFocused: false,
|
isFocused: false,
|
||||||
isOpened: false
|
isOpened: false
|
||||||
@ -93,6 +97,7 @@ export class LocationPicker extends React.Component<
|
|||||||
},
|
},
|
||||||
fn
|
fn
|
||||||
);
|
);
|
||||||
|
this.tempValue = this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
@ -127,6 +132,23 @@ export class LocationPicker extends React.Component<
|
|||||||
this.props.onChange(value);
|
this.props.onChange(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleTempChange(value: any) {
|
||||||
|
if (value) {
|
||||||
|
value = {
|
||||||
|
...value,
|
||||||
|
vendor: this.props.vendor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
this.tempValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleConfirm() {
|
||||||
|
this.props.onChange(this.tempValue);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
@ -139,10 +161,12 @@ export class LocationPicker extends React.Component<
|
|||||||
popOverContainer,
|
popOverContainer,
|
||||||
vendor,
|
vendor,
|
||||||
coordinatesType,
|
coordinatesType,
|
||||||
ak
|
ak,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const __ = this.props.translate;
|
const __ = this.props.translate;
|
||||||
const {isFocused, isOpened} = this.state;
|
const {isFocused, isOpened} = this.state;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
const picker = (() => {
|
const picker = (() => {
|
||||||
switch (vendor) {
|
switch (vendor) {
|
||||||
@ -165,9 +189,9 @@ export class LocationPicker extends React.Component<
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return (<Alert2>{__(`${vendor} 地图控件不支持`, {vendor})}</Alert2>);
|
return <Alert2>{__(`${vendor} 地图控件不支持`, {vendor})}</Alert2>;
|
||||||
}
|
}
|
||||||
})()
|
})();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -178,6 +202,7 @@ export class LocationPicker extends React.Component<
|
|||||||
className={cx(
|
className={cx(
|
||||||
`LocationPicker`,
|
`LocationPicker`,
|
||||||
{
|
{
|
||||||
|
'is-mobile': mobileUI,
|
||||||
'is-disabled': disabled,
|
'is-disabled': disabled,
|
||||||
'is-focused': isFocused,
|
'is-focused': isFocused,
|
||||||
'is-active': isOpened
|
'is-active': isOpened
|
||||||
@ -205,22 +230,55 @@ export class LocationPicker extends React.Component<
|
|||||||
<Icon icon="location" className="icon" />
|
<Icon icon="location" className="icon" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<Overlay
|
{mobileUI ? (
|
||||||
target={this.getTarget}
|
<PopUp
|
||||||
container={popOverContainer || this.getParent}
|
className={cx(`LocationPicker-popup`)}
|
||||||
rootClose={false}
|
container={popOverContainer || this.getParent}
|
||||||
show={isOpened}
|
isShow={isOpened}
|
||||||
>
|
|
||||||
<PopOver
|
|
||||||
className={cx('LocationPicker-popover', popoverClassName)}
|
|
||||||
onHide={this.close}
|
onHide={this.close}
|
||||||
overlay
|
showConfirm
|
||||||
onClick={this.handlePopOverClick}
|
onConfirm={this.handleConfirm}
|
||||||
style={{width: this.getTarget()?.offsetWidth}}
|
|
||||||
>
|
>
|
||||||
{picker}
|
<div className={cx('LocationPicker-popup-inner')}>
|
||||||
</PopOver>
|
{vendor === 'baidu' ? (
|
||||||
</Overlay>
|
<BaiduMapPicker
|
||||||
|
ak={ak}
|
||||||
|
value={value}
|
||||||
|
coordinatesType={coordinatesType}
|
||||||
|
onChange={this.handleTempChange}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Alert2>{__('${vendor} 地图控件不支持', {vendor})}</Alert2>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</PopUp>
|
||||||
|
) : (
|
||||||
|
<Overlay
|
||||||
|
target={this.getTarget}
|
||||||
|
container={popOverContainer || this.getParent}
|
||||||
|
rootClose={false}
|
||||||
|
show={isOpened}
|
||||||
|
>
|
||||||
|
<PopOver
|
||||||
|
className={cx('LocationPicker-popover', popoverClassName)}
|
||||||
|
onHide={this.close}
|
||||||
|
overlay
|
||||||
|
onClick={this.handlePopOverClick}
|
||||||
|
style={{width: this.getTarget()?.offsetWidth}}
|
||||||
|
>
|
||||||
|
{vendor === 'baidu' ? (
|
||||||
|
<BaiduMapPicker
|
||||||
|
ak={ak}
|
||||||
|
value={value}
|
||||||
|
coordinatesType={coordinatesType}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Alert2>{__('${vendor} 地图控件不支持', {vendor})}</Alert2>
|
||||||
|
)}
|
||||||
|
</PopOver>
|
||||||
|
</Overlay>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -264,6 +264,22 @@ export class Modal extends React.Component<ModalProps, ModalState> {
|
|||||||
this.isRootClosed && !e.defaultPrevented && onHide(e);
|
this.isRootClosed && !e.defaultPrevented && onHide(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getZIndex() {
|
||||||
|
let defaultIndex = 1400;
|
||||||
|
const {classnames: cx} = this.props;
|
||||||
|
const modals = document.querySelectorAll('.' + cx('Modal'));
|
||||||
|
const popups = document.querySelectorAll('.' + cx('PopUp'));
|
||||||
|
[...modals, ...popups].forEach((node: HTMLDialogElement) => {
|
||||||
|
const style = getComputedStyle(node);
|
||||||
|
const curIndex = parseInt(style.zIndex, 10);
|
||||||
|
if (curIndex > defaultIndex) {
|
||||||
|
defaultIndex = curIndex;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return defaultIndex;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
@ -301,6 +317,7 @@ export class Modal extends React.Component<ModalProps, ModalState> {
|
|||||||
},
|
},
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
style={{zIndex: this.getZIndex()}}
|
||||||
>
|
>
|
||||||
{overlay ? (
|
{overlay ? (
|
||||||
<div className={cx(`Modal-overlay`, fadeStyles[status])} />
|
<div className={cx(`Modal-overlay`, fadeStyles[status])} />
|
||||||
|
@ -10,7 +10,14 @@ import getMiniDecimal, {
|
|||||||
} from '@rc-component/mini-decimal';
|
} from '@rc-component/mini-decimal';
|
||||||
|
|
||||||
import {Icon} from './icons';
|
import {Icon} from './icons';
|
||||||
import {ThemeProps, themeable, isNumeric, autobind, ucFirst} from 'amis-core';
|
import {
|
||||||
|
ThemeProps,
|
||||||
|
themeable,
|
||||||
|
isNumeric,
|
||||||
|
autobind,
|
||||||
|
ucFirst,
|
||||||
|
isMobile
|
||||||
|
} from 'amis-core';
|
||||||
|
|
||||||
export type ValueType = string | number;
|
export type ValueType = string | number;
|
||||||
|
|
||||||
@ -74,6 +81,7 @@ export interface NumberProps extends ThemeProps {
|
|||||||
* 数字输入框类名
|
* 数字输入框类名
|
||||||
*/
|
*/
|
||||||
inputControlClassName?: string;
|
inputControlClassName?: string;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NumberState {
|
export interface NumberState {
|
||||||
@ -304,11 +312,13 @@ export class NumberInput extends React.Component<NumberProps, NumberState> {
|
|||||||
displayMode,
|
displayMode,
|
||||||
inputRef,
|
inputRef,
|
||||||
keyboard,
|
keyboard,
|
||||||
inputControlClassName
|
inputControlClassName,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const precisionProps: any = {
|
const precisionProps: any = {
|
||||||
precision: NumberInput.normalizePrecision(precision, step)
|
precision: NumberInput.normalizePrecision(precision, step)
|
||||||
};
|
};
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputNumber
|
<InputNumber
|
||||||
@ -320,6 +330,9 @@ export class NumberInput extends React.Component<NumberProps, NumberState> {
|
|||||||
: inputControlClassName,
|
: inputControlClassName,
|
||||||
{
|
{
|
||||||
[`Number--border${ucFirst(borderMode)}`]: borderMode
|
[`Number--border${ucFirst(borderMode)}`]: borderMode
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'is-mobile': mobileUI
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
@ -353,9 +366,11 @@ export class NumberInput extends React.Component<NumberProps, NumberState> {
|
|||||||
borderMode,
|
borderMode,
|
||||||
readOnly,
|
readOnly,
|
||||||
displayMode,
|
displayMode,
|
||||||
inputControlClassName
|
inputControlClassName,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{displayMode === 'enhance' ? (
|
{displayMode === 'enhance' ? (
|
||||||
|
@ -28,7 +28,7 @@ export interface PickerColumnItem {
|
|||||||
visibleItemCount?: number;
|
visibleItemCount?: number;
|
||||||
itemHeight?: number;
|
itemHeight?: number;
|
||||||
options?: PickerOption[];
|
options?: PickerOption[];
|
||||||
optionRender?: (option: string | object | PickerOption) => React.ReactNode;
|
optionRender?: (...params: any) => React.ReactNode;
|
||||||
onChange?: (
|
onChange?: (
|
||||||
value?: PickerOption | string,
|
value?: PickerOption | string,
|
||||||
index?: number,
|
index?: number,
|
||||||
@ -319,7 +319,7 @@ const PickerColumn = forwardRef<{}, PickerColumnProps>((props, ref) => {
|
|||||||
return (
|
return (
|
||||||
<li {...data} ref={menuItemRef}>
|
<li {...data} ref={menuItemRef}>
|
||||||
{props.optionRender ? (
|
{props.optionRender ? (
|
||||||
props.optionRender(option)
|
props.optionRender(option, {index, checked: state.index === index})
|
||||||
) : (
|
) : (
|
||||||
<div {...childData} />
|
<div {...childData} />
|
||||||
)}
|
)}
|
||||||
|
@ -33,6 +33,7 @@ export interface PickerContainerProps
|
|||||||
|
|
||||||
onPickerOpen?: (props: PickerContainerProps) => any;
|
onPickerOpen?: (props: PickerContainerProps) => any;
|
||||||
popOverContainer?: any;
|
popOverContainer?: any;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PickerContainerState {
|
export interface PickerContainerState {
|
||||||
@ -133,7 +134,8 @@ export class PickerContainer extends React.Component<
|
|||||||
size,
|
size,
|
||||||
showFooter,
|
showFooter,
|
||||||
closeOnEsc,
|
closeOnEsc,
|
||||||
popOverContainer
|
popOverContainer,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -156,6 +158,7 @@ export class PickerContainer extends React.Component<
|
|||||||
showFooter={showFooter}
|
showFooter={showFooter}
|
||||||
beforeConfirm={this.confirm}
|
beforeConfirm={this.confirm}
|
||||||
popOverContainer={popOverContainer}
|
popOverContainer={popOverContainer}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
>
|
>
|
||||||
{() =>
|
{() =>
|
||||||
popOverRender({
|
popOverRender({
|
||||||
|
@ -24,12 +24,14 @@ export interface PopOverContainerProps {
|
|||||||
placement?: string;
|
placement?: string;
|
||||||
overlayWidth?: number | string;
|
overlayWidth?: number | string;
|
||||||
overlayWidthField?: 'minWidth' | 'width';
|
overlayWidthField?: 'minWidth' | 'width';
|
||||||
|
showConfirm?: boolean;
|
||||||
// 相当于 placement 的简化版
|
// 相当于 placement 的简化版
|
||||||
align?: OverlayAlignType;
|
align?: OverlayAlignType;
|
||||||
/** Popover层隐藏前触发的事件 */
|
/** Popover层隐藏前触发的事件 */
|
||||||
onBeforeHide?: () => void;
|
onBeforeHide?: () => void;
|
||||||
/** Popover层隐藏后触发的事件 */
|
/** Popover层隐藏后触发的事件 */
|
||||||
onAfterHide?: () => void;
|
onAfterHide?: () => void;
|
||||||
|
onConfirm?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PopOverContainerState {
|
export interface PopOverContainerState {
|
||||||
@ -91,6 +93,12 @@ export class PopOverContainer extends React.Component<
|
|||||||
return this.getTarget()?.parentElement;
|
return this.getTarget()?.parentElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onConfirm() {
|
||||||
|
this.props.onConfirm?.();
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
static calcOverlayWidth(overlay: PopOverOverlay, targetWidth: number) {
|
static calcOverlayWidth(overlay: PopOverOverlay, targetWidth: number) {
|
||||||
const overlayWidth = overlay && overlay.width;
|
const overlayWidth = overlay && overlay.width;
|
||||||
|
|
||||||
@ -142,7 +150,9 @@ export class PopOverContainer extends React.Component<
|
|||||||
popOverClassName,
|
popOverClassName,
|
||||||
popOverRender: dropdownRender,
|
popOverRender: dropdownRender,
|
||||||
placement,
|
placement,
|
||||||
align
|
align,
|
||||||
|
showConfirm,
|
||||||
|
onConfirm
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const mobileUI = useMobileUI && isMobile();
|
const mobileUI = useMobileUI && isMobile();
|
||||||
return (
|
return (
|
||||||
@ -157,7 +167,9 @@ export class PopOverContainer extends React.Component<
|
|||||||
isShow={this.state.isOpened}
|
isShow={this.state.isOpened}
|
||||||
container={popOverContainer}
|
container={popOverContainer}
|
||||||
className={popOverClassName}
|
className={popOverClassName}
|
||||||
|
showConfirm={showConfirm}
|
||||||
onHide={this.close}
|
onHide={this.close}
|
||||||
|
onConfirm={this.onConfirm}
|
||||||
>
|
>
|
||||||
{dropdownRender({onClose: this.close})}
|
{dropdownRender({onClose: this.close})}
|
||||||
</PopUp>
|
</PopUp>
|
||||||
|
@ -71,6 +71,22 @@ export class PopUp extends React.PureComponent<PopUpPorps> {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getZIndex() {
|
||||||
|
let defaultIndex = 3000;
|
||||||
|
const {classnames: cx} = this.props;
|
||||||
|
const modals = document.querySelectorAll('.' + cx('Modal'));
|
||||||
|
const popups = document.querySelectorAll('.' + cx('PopUp'));
|
||||||
|
[...modals, ...popups].forEach((node: HTMLDialogElement) => {
|
||||||
|
const style = getComputedStyle(node);
|
||||||
|
const curIndex = parseInt(style.zIndex, 10);
|
||||||
|
if (curIndex > defaultIndex) {
|
||||||
|
defaultIndex = curIndex;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return defaultIndex;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
style,
|
style,
|
||||||
@ -93,7 +109,8 @@ export class PopUp extends React.PureComponent<PopUpPorps> {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const outerStyle: any = {
|
const outerStyle: any = {
|
||||||
...style
|
...style,
|
||||||
|
zIndex: this.getZIndex()
|
||||||
};
|
};
|
||||||
delete outerStyle.top;
|
delete outerStyle.top;
|
||||||
return (
|
return (
|
||||||
|
@ -17,6 +17,7 @@ import type {ThemeProps} from 'amis-core';
|
|||||||
import {themeable} from 'amis-core';
|
import {themeable} from 'amis-core';
|
||||||
import {autobind, camel} from 'amis-core';
|
import {autobind, camel} from 'amis-core';
|
||||||
import {stripNumber} from 'amis-core';
|
import {stripNumber} from 'amis-core';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
import {findDOMNode} from 'react-dom';
|
import {findDOMNode} from 'react-dom';
|
||||||
import {Icon} from './icons';
|
import {Icon} from './icons';
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ interface HandleItemProps extends ThemeProps {
|
|||||||
tipFormatter?: (value: Value) => boolean;
|
tipFormatter?: (value: Value) => boolean;
|
||||||
unit?: string;
|
unit?: string;
|
||||||
tooltipPlacement?: string;
|
tooltipPlacement?: string;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LabelProps extends ThemeProps {
|
interface LabelProps extends ThemeProps {
|
||||||
@ -166,6 +168,35 @@ class HandleItem extends React.Component<HandleItemProps, HandleItemState> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onTouchStart() {
|
||||||
|
this.setState({
|
||||||
|
isDrag: true,
|
||||||
|
labelActive: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onTouchMove(e: any) {
|
||||||
|
const {isDrag} = this.state;
|
||||||
|
const {type = 'min'} = this.props;
|
||||||
|
if (!isDrag) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.props.onChange(e.touches[0].clientX, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onTouchEnd() {
|
||||||
|
const {isDrag} = this.state;
|
||||||
|
if (isDrag) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
labelActive: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
@ -176,7 +207,8 @@ class HandleItem extends React.Component<HandleItemProps, HandleItemState> {
|
|||||||
tooltipVisible,
|
tooltipVisible,
|
||||||
tipFormatter,
|
tipFormatter,
|
||||||
unit,
|
unit,
|
||||||
tooltipPlacement = 'auto'
|
tooltipPlacement = 'auto',
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {isDrag, labelActive} = this.state;
|
const {isDrag, labelActive} = this.state;
|
||||||
const style = {
|
const style = {
|
||||||
@ -184,6 +216,8 @@ class HandleItem extends React.Component<HandleItemProps, HandleItemState> {
|
|||||||
zIndex: isDrag ? 2 : 1
|
zIndex: isDrag ? 2 : 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return disabled ? (
|
return disabled ? (
|
||||||
<div className={cx('InputRange-handle')} style={style}>
|
<div className={cx('InputRange-handle')} style={style}>
|
||||||
<div className={cx('InputRange-handle-icon')}>
|
<div className={cx('InputRange-handle-icon')}>
|
||||||
@ -192,7 +226,9 @@ class HandleItem extends React.Component<HandleItemProps, HandleItemState> {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
className={cx('InputRange-handle')}
|
className={cx('InputRange-handle', {
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
})}
|
||||||
style={style}
|
style={style}
|
||||||
ref={this.handleRef}
|
ref={this.handleRef}
|
||||||
>
|
>
|
||||||
@ -203,6 +239,9 @@ class HandleItem extends React.Component<HandleItemProps, HandleItemState> {
|
|||||||
onMouseDown={this.onMouseDown}
|
onMouseDown={this.onMouseDown}
|
||||||
onMouseEnter={this.onMouseEnter}
|
onMouseEnter={this.onMouseEnter}
|
||||||
onMouseLeave={this.onMouseLeave}
|
onMouseLeave={this.onMouseLeave}
|
||||||
|
onTouchStart={this.onTouchStart}
|
||||||
|
onTouchMove={this.onTouchMove}
|
||||||
|
onTouchEnd={this.onTouchEnd}
|
||||||
>
|
>
|
||||||
<Icon icon="slider-handle" className="icon" />
|
<Icon icon="slider-handle" className="icon" />
|
||||||
</div>
|
</div>
|
||||||
@ -277,6 +316,7 @@ class Label extends React.Component<LabelProps, any> {
|
|||||||
// @todo 丰富这个
|
// @todo 丰富这个
|
||||||
export interface RangeItemProps extends ThemeProps {
|
export interface RangeItemProps extends ThemeProps {
|
||||||
[propName: string]: any;
|
[propName: string]: any;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Range extends React.Component<RangeItemProps, any> {
|
export class Range extends React.Component<RangeItemProps, any> {
|
||||||
@ -443,13 +483,15 @@ export class Range extends React.Component<RangeItemProps, any> {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
@autobind
|
@autobind
|
||||||
getOffsetLeft(value: number | string) {
|
getOffsetLeft(value: number | string, getNumber?: boolean) {
|
||||||
const {max, min} = this.props;
|
const {max, min} = this.props;
|
||||||
if (isString(value) && MARKS_REG.test(value)) {
|
if (isString(value) && MARKS_REG.test(value)) {
|
||||||
return value;
|
return getNumber ? parseFloat(value) : value;
|
||||||
}
|
}
|
||||||
value = Math.min(Math.max(+value, min), max);
|
value = Math.min(Math.max(+value, min), max);
|
||||||
return ((value - min) * 100) / (max - min) + '%';
|
return getNumber
|
||||||
|
? ((value - min) * 100) / (max - min)
|
||||||
|
: ((value - min) * 100) / (max - min) + '%';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -489,7 +531,8 @@ export class Range extends React.Component<RangeItemProps, any> {
|
|||||||
unit,
|
unit,
|
||||||
tooltipPlacement,
|
tooltipPlacement,
|
||||||
tipFormatter,
|
tipFormatter,
|
||||||
onAfterChange
|
onAfterChange,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// trace
|
// trace
|
||||||
@ -520,6 +563,14 @@ export class Range extends React.Component<RangeItemProps, any> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sortMaks = marks
|
||||||
|
? keys(marks).sort(
|
||||||
|
(a: keyof MarksType, b: keyof MarksType) =>
|
||||||
|
(this.getOffsetLeft(a, true) as number) -
|
||||||
|
(this.getOffsetLeft(b, true) as number)
|
||||||
|
)
|
||||||
|
: [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx('InputRange-wrap')}>
|
<div className={cx('InputRange-wrap')}>
|
||||||
<div
|
<div
|
||||||
@ -550,6 +601,7 @@ export class Range extends React.Component<RangeItemProps, any> {
|
|||||||
tooltipVisible={tooltipVisible}
|
tooltipVisible={tooltipVisible}
|
||||||
tipFormatter={tipFormatter}
|
tipFormatter={tipFormatter}
|
||||||
unit={unit}
|
unit={unit}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
tooltipPlacement={tooltipPlacement}
|
tooltipPlacement={tooltipPlacement}
|
||||||
onAfterChange={onAfterChange}
|
onAfterChange={onAfterChange}
|
||||||
onChange={this.onGetChangeValue.bind(this)}
|
onChange={this.onGetChangeValue.bind(this)}
|
||||||
@ -566,6 +618,7 @@ export class Range extends React.Component<RangeItemProps, any> {
|
|||||||
tooltipVisible={tooltipVisible}
|
tooltipVisible={tooltipVisible}
|
||||||
tipFormatter={tipFormatter}
|
tipFormatter={tipFormatter}
|
||||||
unit={unit}
|
unit={unit}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
tooltipPlacement={tooltipPlacement}
|
tooltipPlacement={tooltipPlacement}
|
||||||
onAfterChange={onAfterChange}
|
onAfterChange={onAfterChange}
|
||||||
onChange={this.onChange.bind(this)}
|
onChange={this.onChange.bind(this)}
|
||||||
@ -575,9 +628,10 @@ export class Range extends React.Component<RangeItemProps, any> {
|
|||||||
{/* 刻度标记 */}
|
{/* 刻度标记 */}
|
||||||
{marks && (
|
{marks && (
|
||||||
<div className={cx('InputRange-marks')}>
|
<div className={cx('InputRange-marks')}>
|
||||||
{keys(marks).map((key: keyof MarksType) => {
|
{sortMaks.map((key: keyof MarksType) => {
|
||||||
const offsetLeft = this.getOffsetLeft(key);
|
const offsetLeft = this.getOffsetLeft(key) as string;
|
||||||
const markMaxWidth = this.getMarkMaxWidth(key, marks);
|
const markMaxWidth = this.getMarkMaxWidth(key, marks);
|
||||||
|
|
||||||
if (MARKS_REG.test(offsetLeft)) {
|
if (MARKS_REG.test(offsetLeft)) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -29,16 +29,22 @@ export interface ResultBoxProps
|
|||||||
overflowTagPopover?: TooltipObject;
|
overflowTagPopover?: TooltipObject;
|
||||||
actions?: JSX.Element | JSX.Element[];
|
actions?: JSX.Element | JSX.Element[];
|
||||||
showInvalidMatch?: boolean;
|
showInvalidMatch?: boolean;
|
||||||
|
showArrow?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResultBox extends React.Component<ResultBoxProps> {
|
export class ResultBox extends React.Component<ResultBoxProps> {
|
||||||
static defaultProps: Pick<
|
static defaultProps: Pick<
|
||||||
ResultBoxProps,
|
ResultBoxProps,
|
||||||
'clearable' | 'placeholder' | 'itemRender' | 'inputPlaceholder'
|
| 'clearable'
|
||||||
|
| 'placeholder'
|
||||||
|
| 'itemRender'
|
||||||
|
| 'inputPlaceholder'
|
||||||
|
| 'showArrow'
|
||||||
> = {
|
> = {
|
||||||
clearable: false,
|
clearable: false,
|
||||||
placeholder: 'placeholder.noData',
|
placeholder: 'placeholder.noData',
|
||||||
inputPlaceholder: 'placeholder.enter',
|
inputPlaceholder: 'placeholder.enter',
|
||||||
|
showArrow: true,
|
||||||
itemRender: (option: any) => (
|
itemRender: (option: any) => (
|
||||||
<span>{`${option.scopeLabel || ''}${option.label}`}</span>
|
<span>{`${option.scopeLabel || ''}${option.label}`}</span>
|
||||||
)
|
)
|
||||||
@ -68,6 +74,7 @@ export class ResultBox extends React.Component<ResultBoxProps> {
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleFocus(e: any) {
|
handleFocus(e: any) {
|
||||||
|
console.log('eeeeeeee', e);
|
||||||
const onFocus = this.props.onFocus;
|
const onFocus = this.props.onFocus;
|
||||||
onFocus && onFocus(e);
|
onFocus && onFocus(e);
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -241,11 +248,14 @@ export class ResultBox extends React.Component<ResultBoxProps> {
|
|||||||
onClear,
|
onClear,
|
||||||
maxTagCount,
|
maxTagCount,
|
||||||
overflowTagPopover,
|
overflowTagPopover,
|
||||||
|
showArrow,
|
||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const isFocused = this.state.isFocused;
|
const isFocused = this.state.isFocused;
|
||||||
const mobileUI = useMobileUI && isMobile();
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
|
console.log('onResultClick-----', onResultClick);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx('ResultBox', className, {
|
className={cx('ResultBox', className, {
|
||||||
@ -326,7 +336,7 @@ export class ResultBox extends React.Component<ResultBoxProps> {
|
|||||||
<Icon icon="right-arrow-bold" className="icon" />
|
<Icon icon="right-arrow-bold" className="icon" />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{!allowInput && mobileUI ? (
|
{!allowInput && mobileUI && showArrow ? (
|
||||||
<span className={cx('ResultBox-arrow')}>
|
<span className={cx('ResultBox-arrow')}>
|
||||||
<Icon icon="caret" className="icon" />
|
<Icon icon="caret" className="icon" />
|
||||||
</span>
|
</span>
|
||||||
|
@ -6,7 +6,7 @@ import moment from 'moment';
|
|||||||
import {ThemeProps, themeable} from 'amis-core';
|
import {ThemeProps, themeable} from 'amis-core';
|
||||||
import {Icon} from './icons';
|
import {Icon} from './icons';
|
||||||
import {uncontrollable} from 'amis-core';
|
import {uncontrollable} from 'amis-core';
|
||||||
import {autobind} from 'amis-core';
|
import {autobind, isMobile} from 'amis-core';
|
||||||
import {LocaleProps, localeable} from 'amis-core';
|
import {LocaleProps, localeable} from 'amis-core';
|
||||||
|
|
||||||
export interface HistoryRecord {
|
export interface HistoryRecord {
|
||||||
@ -48,6 +48,7 @@ export interface SearchBoxProps extends ThemeProps, LocaleProps {
|
|||||||
/** 历史记录配置 */
|
/** 历史记录配置 */
|
||||||
history?: SearchHistoryOptions;
|
history?: SearchHistoryOptions;
|
||||||
clearAndSubmit?: boolean;
|
clearAndSubmit?: boolean;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchBoxState {
|
export interface SearchBoxState {
|
||||||
@ -284,10 +285,12 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
|
|||||||
mini,
|
mini,
|
||||||
enhance,
|
enhance,
|
||||||
clearable,
|
clearable,
|
||||||
|
useMobileUI,
|
||||||
translate: __
|
translate: __
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {isFocused, inputValue} = this.state;
|
const {isFocused, inputValue} = this.state;
|
||||||
const {enable} = this.getHistoryOptions();
|
const {enable} = this.getHistoryOptions();
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -298,7 +301,8 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
|
|||||||
disabled ? 'is-disabled' : '',
|
disabled ? 'is-disabled' : '',
|
||||||
isFocused ? 'is-focused' : '',
|
isFocused ? 'is-focused' : '',
|
||||||
!mini || active ? 'is-active' : '',
|
!mini || active ? 'is-active' : '',
|
||||||
{'is-history': enable}
|
{'is-history': enable},
|
||||||
|
{'is-mobile': mobileUI}
|
||||||
)}
|
)}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
|
@ -41,6 +41,7 @@ import {RemoteOptionsProps, withRemoteConfig} from './WithRemoteConfig';
|
|||||||
import Picker from './Picker';
|
import Picker from './Picker';
|
||||||
import PopUp from './PopUp';
|
import PopUp from './PopUp';
|
||||||
import BasePopover, {PopOverOverlay} from './PopOverContainer';
|
import BasePopover, {PopOverOverlay} from './PopOverContainer';
|
||||||
|
import SelectMobile from './SelectMobile';
|
||||||
|
|
||||||
import type {TooltipObject} from '../components/TooltipWrapper';
|
import type {TooltipObject} from '../components/TooltipWrapper';
|
||||||
|
|
||||||
@ -303,7 +304,7 @@ export function normalizeOptions(
|
|||||||
|
|
||||||
const DownshiftChangeTypes = Downshift.stateChangeTypes;
|
const DownshiftChangeTypes = Downshift.stateChangeTypes;
|
||||||
|
|
||||||
interface SelectProps
|
export interface SelectProps
|
||||||
extends OptionProps,
|
extends OptionProps,
|
||||||
ThemeProps,
|
ThemeProps,
|
||||||
LocaleProps,
|
LocaleProps,
|
||||||
@ -1145,10 +1146,7 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const mobileUI = isMobile() && useMobileUI;
|
const mobileUI = isMobile() && useMobileUI;
|
||||||
const column = {
|
|
||||||
labelField: 'label',
|
|
||||||
options: filtedOptions
|
|
||||||
};
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<div
|
<div
|
||||||
ref={this.menu}
|
ref={this.menu}
|
||||||
@ -1229,14 +1227,21 @@ export class Select extends React.Component<SelectProps, SelectState> {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return mobileUI ? (
|
return mobileUI ? (
|
||||||
<PopUp
|
<SelectMobile
|
||||||
className={cx(`Select-popup`)}
|
{...this.props}
|
||||||
container={popOverContainer}
|
highlightedIndex={highlightedIndex}
|
||||||
isShow={this.state.isOpen}
|
isOpen={isOpen}
|
||||||
onHide={this.close}
|
getItemProps={getItemProps}
|
||||||
>
|
getInputProps={getInputProps}
|
||||||
{menu}
|
selectedItem={selectedItem}
|
||||||
</PopUp>
|
onChange={selection => {
|
||||||
|
this.setState({
|
||||||
|
isOpen: false
|
||||||
|
});
|
||||||
|
this.props.onChange(selection);
|
||||||
|
}}
|
||||||
|
onClose={this.close}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Overlay
|
<Overlay
|
||||||
container={popOverContainer || this.getTarget}
|
container={popOverContainer || this.getTarget}
|
||||||
|
520
packages/amis-ui/src/components/SelectMobile.tsx
Normal file
520
packages/amis-ui/src/components/SelectMobile.tsx
Normal file
@ -0,0 +1,520 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {findDOMNode} from 'react-dom';
|
||||||
|
import Picker from './Picker';
|
||||||
|
import PopUp from './PopUp';
|
||||||
|
import {autobind, highlight} from 'amis-core';
|
||||||
|
import merge from 'lodash/merge';
|
||||||
|
// @ts-ignore
|
||||||
|
import {matchSorter} from 'match-sorter';
|
||||||
|
import {Option, Options, value2array, SelectProps} from './Select';
|
||||||
|
import VirtualList from './virtual-list';
|
||||||
|
import Checkbox from './Checkbox';
|
||||||
|
import Input from './Input';
|
||||||
|
import {closeIcon, Icon} from './icons';
|
||||||
|
|
||||||
|
interface SelectState {
|
||||||
|
isFocused: boolean;
|
||||||
|
inputValue: string;
|
||||||
|
itemHeight: number;
|
||||||
|
selection: Array<Option>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props extends SelectProps {
|
||||||
|
isOpen: boolean;
|
||||||
|
highlightedIndex: any;
|
||||||
|
selectedItem: any;
|
||||||
|
getInputProps: (...params: any) => any;
|
||||||
|
getItemProps: (...params: any) => any;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class SelectMobile extends React.Component<Props, SelectState> {
|
||||||
|
input: HTMLInputElement;
|
||||||
|
target: HTMLElement;
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
selection: value2array(props.value, props),
|
||||||
|
isFocused: false,
|
||||||
|
inputValue: '',
|
||||||
|
itemHeight: 32 /** Select选项高度保持一致 */
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleChange([item]: any) {
|
||||||
|
const {onChange, multiple, simpleValue, valueField, options} = this.props;
|
||||||
|
let {selection} = this.state;
|
||||||
|
|
||||||
|
if (!multiple && item === undefined) {
|
||||||
|
console.log('执行了');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单选是字符串
|
||||||
|
const selectItem = options.find((option: Option) =>
|
||||||
|
multiple
|
||||||
|
? option[valueField] === item[valueField]
|
||||||
|
: option[valueField] === item
|
||||||
|
);
|
||||||
|
if (multiple) {
|
||||||
|
const selectionValues = selection.map(item => item[valueField]);
|
||||||
|
selection = selection.concat();
|
||||||
|
const idx = selectionValues.indexOf(selectItem?.[valueField]);
|
||||||
|
if (~idx) {
|
||||||
|
selection.splice(idx, 1);
|
||||||
|
} else {
|
||||||
|
selectItem && selection.push(selectItem);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
selection
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
selection: selectItem ? [selectItem] : []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleInputChange(evt: React.ChangeEvent<HTMLInputElement>) {
|
||||||
|
const {loadOptions} = this.props;
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
inputValue: evt.currentTarget.value
|
||||||
|
},
|
||||||
|
() => loadOptions && loadOptions(this.state.inputValue)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
getTarget() {
|
||||||
|
if (!this.target) {
|
||||||
|
this.target = findDOMNode(this) as HTMLElement;
|
||||||
|
}
|
||||||
|
return this.target as HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
inputRef(ref: HTMLInputElement) {
|
||||||
|
this.input = ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
toggleCheckAll() {
|
||||||
|
const {
|
||||||
|
options,
|
||||||
|
onChange,
|
||||||
|
simpleValue,
|
||||||
|
checkAllBySearch,
|
||||||
|
labelField,
|
||||||
|
valueField
|
||||||
|
} = this.props;
|
||||||
|
const inputValue = this.state.inputValue;
|
||||||
|
let {selection} = this.state;
|
||||||
|
let filtedOptions: Array<Option> =
|
||||||
|
inputValue && checkAllBySearch !== false
|
||||||
|
? matchSorter(options, inputValue, {
|
||||||
|
keys: [labelField || 'label', valueField || 'value']
|
||||||
|
})
|
||||||
|
: options.concat();
|
||||||
|
const optionsValues = filtedOptions.map(option => option.value);
|
||||||
|
const selectionValues = selection.map(select => select.value);
|
||||||
|
const checkedAll = optionsValues.every(
|
||||||
|
option => selectionValues.indexOf(option) > -1
|
||||||
|
);
|
||||||
|
|
||||||
|
selection = checkedAll ? [] : filtedOptions;
|
||||||
|
|
||||||
|
this.setState({selection});
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleAddClick() {
|
||||||
|
const {onAdd} = this.props;
|
||||||
|
onAdd && onAdd();
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleEditClick(e: Event, item: any) {
|
||||||
|
const {onEdit} = this.props;
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
onEdit && onEdit(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleDeleteClick(e: Event, item: any) {
|
||||||
|
const {onDelete} = this.props;
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
onDelete && onDelete(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onFocus(e: any) {
|
||||||
|
const {simpleValue} = this.props;
|
||||||
|
const {selection} = this.state;
|
||||||
|
const value = simpleValue ? selection.map(item => item.value) : selection;
|
||||||
|
|
||||||
|
this.props.disabled ||
|
||||||
|
this.props.isOpen ||
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
isFocused: true
|
||||||
|
},
|
||||||
|
this.focus
|
||||||
|
);
|
||||||
|
|
||||||
|
this.props.onFocus &&
|
||||||
|
this.props.onFocus({
|
||||||
|
...e,
|
||||||
|
value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onBlur(e: any) {
|
||||||
|
const {simpleValue} = this.props;
|
||||||
|
const {selection} = this.state;
|
||||||
|
const value = simpleValue ? selection.map(item => item.value) : selection;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
isFocused: false
|
||||||
|
});
|
||||||
|
|
||||||
|
this.props.onBlur &&
|
||||||
|
this.props.onBlur({
|
||||||
|
...e,
|
||||||
|
value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
focus() {
|
||||||
|
this.input
|
||||||
|
? this.input.focus()
|
||||||
|
: this.getTarget() && this.getTarget().focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
blur() {
|
||||||
|
this.input
|
||||||
|
? this.input.blur()
|
||||||
|
: this.getTarget() && this.getTarget().blur();
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
clearSearchValue() {
|
||||||
|
const {loadOptions} = this.props;
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
inputValue: ''
|
||||||
|
},
|
||||||
|
() => loadOptions?.('')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onConfirm() {
|
||||||
|
const {selection} = this.state;
|
||||||
|
const {
|
||||||
|
multiple,
|
||||||
|
onChange,
|
||||||
|
simpleValue,
|
||||||
|
valueField,
|
||||||
|
options,
|
||||||
|
loadOptions,
|
||||||
|
labelField
|
||||||
|
} = this.props;
|
||||||
|
if (multiple) {
|
||||||
|
onChange(
|
||||||
|
simpleValue ? selection.map(item => item[valueField]) : selection
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const inputValue = this.state.inputValue;
|
||||||
|
let filtedOptions: Array<Option> = (
|
||||||
|
inputValue && !loadOptions
|
||||||
|
? matchSorter(options, inputValue, {
|
||||||
|
keys: [labelField || 'label', valueField || 'value']
|
||||||
|
})
|
||||||
|
: options.concat()
|
||||||
|
).filter((option: Option) => !option.hidden && option.visible !== false);
|
||||||
|
// picker 打开未滑动时选中第一项
|
||||||
|
if (!selection.length && filtedOptions.length) {
|
||||||
|
onChange(
|
||||||
|
simpleValue ? filtedOptions[0]?.[valueField] : filtedOptions[0]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
onChange(simpleValue ? selection[0]?.[valueField] : selection[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
popOverContainer,
|
||||||
|
options,
|
||||||
|
value,
|
||||||
|
valueField,
|
||||||
|
labelField,
|
||||||
|
noResultsText,
|
||||||
|
loadOptions,
|
||||||
|
creatable,
|
||||||
|
multiple,
|
||||||
|
valuesNoWrap,
|
||||||
|
classnames: cx,
|
||||||
|
popoverClassName,
|
||||||
|
popOverContainerSelector,
|
||||||
|
checkAll,
|
||||||
|
checkAllLabel,
|
||||||
|
checkAllBySearch,
|
||||||
|
searchable,
|
||||||
|
createBtnLabel,
|
||||||
|
disabled,
|
||||||
|
searchPromptText,
|
||||||
|
editable,
|
||||||
|
removable,
|
||||||
|
overlayPlacement,
|
||||||
|
translate: __,
|
||||||
|
hideSelected,
|
||||||
|
renderMenu,
|
||||||
|
mobileClassName,
|
||||||
|
virtualThreshold = 100,
|
||||||
|
useMobileUI = false,
|
||||||
|
overlay,
|
||||||
|
isOpen,
|
||||||
|
highlightedIndex,
|
||||||
|
onClose,
|
||||||
|
getInputProps,
|
||||||
|
getItemProps,
|
||||||
|
selectedItem
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const {selection} = this.state;
|
||||||
|
|
||||||
|
const inputValue = this.state.inputValue;
|
||||||
|
let checkedAll = false;
|
||||||
|
let checkedPartial = false;
|
||||||
|
let filtedOptions: Array<Option> = (
|
||||||
|
inputValue && isOpen && !loadOptions
|
||||||
|
? matchSorter(options, inputValue, {
|
||||||
|
keys: [labelField || 'label', valueField || 'value']
|
||||||
|
})
|
||||||
|
: options.concat()
|
||||||
|
).filter((option: Option) => !option.hidden && option.visible !== false);
|
||||||
|
|
||||||
|
const enableVirtualRender =
|
||||||
|
filtedOptions.length && filtedOptions.length > virtualThreshold;
|
||||||
|
const selectionValues = selection.map(select => select[valueField]);
|
||||||
|
if (multiple && checkAll) {
|
||||||
|
const optionsValues = (
|
||||||
|
checkAllBySearch !== false ? filtedOptions : options
|
||||||
|
).map(option => option[valueField]);
|
||||||
|
|
||||||
|
checkedAll = optionsValues.every(
|
||||||
|
option => selectionValues.indexOf(option) > -1
|
||||||
|
);
|
||||||
|
checkedPartial = optionsValues.some(
|
||||||
|
option => selectionValues.indexOf(option) > -1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用于虚拟渲染的每项高度
|
||||||
|
const virtualItemHeight = this.props.itemHeight || this.state.itemHeight;
|
||||||
|
|
||||||
|
// 渲染单个选项
|
||||||
|
const renderItem = ({index, style}: {index: number; style?: object}) => {
|
||||||
|
const item = filtedOptions[index];
|
||||||
|
if (!item) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const checked =
|
||||||
|
selectedItem === item || !!~selectionValues.indexOf(item[valueField]);
|
||||||
|
|
||||||
|
if (hideSelected && checked) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
{...getItemProps({
|
||||||
|
key:
|
||||||
|
typeof item.value === 'string'
|
||||||
|
? `${item.label}-${item.value}`
|
||||||
|
: index,
|
||||||
|
index,
|
||||||
|
item,
|
||||||
|
disabled: item.disabled
|
||||||
|
})}
|
||||||
|
style={merge(style, enableVirtualRender ? {width: '100%'} : {})}
|
||||||
|
className={cx(`Select-option`, {
|
||||||
|
'is-disabled': item.disabled,
|
||||||
|
'is-active': checked,
|
||||||
|
'is-mobile': true
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{renderMenu ? (
|
||||||
|
multiple ? (
|
||||||
|
renderMenu(item, {
|
||||||
|
multiple,
|
||||||
|
checkAll,
|
||||||
|
checked,
|
||||||
|
onChange: () => this.handleChange(item),
|
||||||
|
inputValue: inputValue || '',
|
||||||
|
searchable,
|
||||||
|
index
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
renderMenu(item, {
|
||||||
|
multiple,
|
||||||
|
checkAll,
|
||||||
|
checked,
|
||||||
|
onChange: () => this.handleChange(item),
|
||||||
|
inputValue: inputValue || '',
|
||||||
|
searchable,
|
||||||
|
index
|
||||||
|
})
|
||||||
|
)
|
||||||
|
) : multiple ? (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
title={item[labelField]}
|
||||||
|
className={cx('Select-option-item-check')}
|
||||||
|
onClick={() => !item.disabled && this.handleChange([item])}
|
||||||
|
>
|
||||||
|
{item.disabled
|
||||||
|
? item[labelField]
|
||||||
|
: highlight(
|
||||||
|
item[labelField],
|
||||||
|
inputValue as string,
|
||||||
|
cx('Select-option-hl')
|
||||||
|
)}
|
||||||
|
|
||||||
|
{item.tip}
|
||||||
|
</div>
|
||||||
|
{checked ? (
|
||||||
|
<Icon icon="check" className={cx('Select-option-mcheck')} />
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
className={cx('Select-option-content')}
|
||||||
|
title={
|
||||||
|
typeof item[labelField] === 'string' ? item[labelField] : ''
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{item.disabled
|
||||||
|
? item[labelField]
|
||||||
|
: highlight(
|
||||||
|
item[labelField],
|
||||||
|
inputValue as string,
|
||||||
|
cx('Select-option-hl')
|
||||||
|
)}
|
||||||
|
{item.tip}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const menu = (
|
||||||
|
<div
|
||||||
|
className={cx('Select-menu', {
|
||||||
|
'Select--longlist': enableVirtualRender,
|
||||||
|
'is-mobile': true
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{searchable ? (
|
||||||
|
<div
|
||||||
|
className={cx(`Select-input`, {
|
||||||
|
'is-focused': this.state.isFocused
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Icon icon="search" className="icon" />
|
||||||
|
<Input
|
||||||
|
{...getInputProps({
|
||||||
|
onFocus: this.onFocus,
|
||||||
|
onBlur: this.onBlur,
|
||||||
|
disabled: disabled,
|
||||||
|
placeholder: __(searchPromptText),
|
||||||
|
onChange: this.handleInputChange,
|
||||||
|
ref: this.inputRef
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
{inputValue?.length ? (
|
||||||
|
<a onClick={this.clearSearchValue} className={cx('Select-clear')}>
|
||||||
|
<Icon icon="close" className="icon" />
|
||||||
|
</a>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{multiple && valuesNoWrap ? (
|
||||||
|
<div className={cx('Select-option')}>
|
||||||
|
已选择({selectionValues.length})
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{multiple && checkAll && filtedOptions.length ? (
|
||||||
|
<div className={cx('Select-option')}>
|
||||||
|
<Checkbox
|
||||||
|
checked={checkedPartial}
|
||||||
|
partial={checkedPartial && !checkedAll}
|
||||||
|
onChange={this.toggleCheckAll}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
{__(checkAllLabel)}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{filtedOptions.length ? (
|
||||||
|
filtedOptions.length > virtualThreshold ? ( // 较多数据时才启用 virtuallist,避免滚动条问题
|
||||||
|
<VirtualList
|
||||||
|
height={
|
||||||
|
filtedOptions.length > 8
|
||||||
|
? 266
|
||||||
|
: filtedOptions.length * virtualItemHeight
|
||||||
|
}
|
||||||
|
itemCount={filtedOptions.length}
|
||||||
|
itemSize={virtualItemHeight}
|
||||||
|
renderItem={renderItem}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
filtedOptions.map((item, index) => {
|
||||||
|
return renderItem({index});
|
||||||
|
})
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<div className={cx('Select-noResult')}>{__(noResultsText)}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PopUp
|
||||||
|
className={cx(`Select-popup`)}
|
||||||
|
container={popOverContainer}
|
||||||
|
isShow={isOpen}
|
||||||
|
showConfirm={true}
|
||||||
|
onConfirm={this.onConfirm}
|
||||||
|
onHide={onClose}
|
||||||
|
>
|
||||||
|
{multiple ? (
|
||||||
|
menu
|
||||||
|
) : (
|
||||||
|
<Picker
|
||||||
|
className={'Select-picker'}
|
||||||
|
columns={{
|
||||||
|
options: filtedOptions as Option[],
|
||||||
|
optionRender: renderMenu
|
||||||
|
}}
|
||||||
|
onChange={item => this.handleChange(item as any)}
|
||||||
|
showToolbar={false}
|
||||||
|
labelField={labelField}
|
||||||
|
valueField={valueField}
|
||||||
|
itemHeight={40}
|
||||||
|
value={[selection[0]?.[valueField]]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</PopUp>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ import {Icon} from './icons';
|
|||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import {findDOMNode} from 'react-dom';
|
import {findDOMNode} from 'react-dom';
|
||||||
import TooltipWrapper from './TooltipWrapper';
|
import TooltipWrapper from './TooltipWrapper';
|
||||||
import {resizeSensor} from 'amis-core';
|
import {resizeSensor, isMobile} from 'amis-core';
|
||||||
import PopOverContainer from './PopOverContainer';
|
import PopOverContainer from './PopOverContainer';
|
||||||
|
|
||||||
import Sortable from 'sortablejs';
|
import Sortable from 'sortablejs';
|
||||||
@ -45,6 +45,8 @@ export interface TabProps extends ThemeProps {
|
|||||||
iconPosition?: 'left' | 'right';
|
iconPosition?: 'left' | 'right';
|
||||||
disabled?: boolean | string;
|
disabled?: boolean | string;
|
||||||
eventKey: string | number;
|
eventKey: string | number;
|
||||||
|
prevKey?: string | number;
|
||||||
|
nextKey?: string | number;
|
||||||
tab?: Schema;
|
tab?: Schema;
|
||||||
className?: string;
|
className?: string;
|
||||||
activeKey?: string | number;
|
activeKey?: string | number;
|
||||||
@ -53,12 +55,52 @@ export interface TabProps extends ThemeProps {
|
|||||||
unmountOnExit?: boolean;
|
unmountOnExit?: boolean;
|
||||||
toolbar?: React.ReactNode;
|
toolbar?: React.ReactNode;
|
||||||
children?: React.ReactNode | Array<React.ReactNode>;
|
children?: React.ReactNode | Array<React.ReactNode>;
|
||||||
|
useMobileUI?: boolean;
|
||||||
|
swipeable?: boolean;
|
||||||
|
onSelect?: (eventKey: string | number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
class TabComponent extends React.PureComponent<TabProps> {
|
class TabComponent extends React.PureComponent<TabProps> {
|
||||||
contentDom: any;
|
contentDom: any;
|
||||||
|
touch: any = {};
|
||||||
|
touchStartTime: number;
|
||||||
contentRef = (ref: any) => (this.contentDom = ref);
|
contentRef = (ref: any) => (this.contentDom = ref);
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onTouchStart(event: TouchEvent) {
|
||||||
|
this.touch.startX = event.touches[0].clientX;
|
||||||
|
this.touch.startY = event.touches[0].clientY;
|
||||||
|
this.touchStartTime = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onTouchMove(event: TouchEvent) {
|
||||||
|
const touch = event.touches[0];
|
||||||
|
const newState = {...this.touch};
|
||||||
|
|
||||||
|
newState.deltaX = touch.clientX < 0 ? 0 : touch.clientX - newState.startX;
|
||||||
|
newState.deltaY = touch.clientY - newState.startY;
|
||||||
|
newState.offsetX = Math.abs(newState.deltaX);
|
||||||
|
newState.offsetY = Math.abs(newState.deltaY);
|
||||||
|
this.touch = newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onTouchEnd() {
|
||||||
|
const duration = Date.now() - this.touchStartTime;
|
||||||
|
const speed = this.touch.deltaX / duration;
|
||||||
|
const shouldSwipe = Math.abs(speed) > 0.25;
|
||||||
|
const {prevKey, nextKey, onSelect} = this.props;
|
||||||
|
|
||||||
|
if (shouldSwipe) {
|
||||||
|
if (this.touch.deltaX > 0) {
|
||||||
|
prevKey !== undefined && onSelect?.(prevKey);
|
||||||
|
} else {
|
||||||
|
nextKey && onSelect?.(nextKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
@ -68,9 +110,13 @@ class TabComponent extends React.PureComponent<TabProps> {
|
|||||||
eventKey,
|
eventKey,
|
||||||
activeKey,
|
activeKey,
|
||||||
children,
|
children,
|
||||||
className
|
className,
|
||||||
|
swipeable,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Transition
|
<Transition
|
||||||
in={activeKey === eventKey}
|
in={activeKey === eventKey}
|
||||||
@ -91,6 +137,10 @@ class TabComponent extends React.PureComponent<TabProps> {
|
|||||||
'Tabs-pane',
|
'Tabs-pane',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
onTouchStart={swipeable && mobileUI && this.onTouchStart}
|
||||||
|
onTouchMove={swipeable && mobileUI && this.onTouchMove}
|
||||||
|
onTouchEnd={swipeable && mobileUI && this.onTouchEnd}
|
||||||
|
onTouchCancel={swipeable && mobileUI && this.onTouchEnd}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
@ -132,6 +182,7 @@ export interface TabsProps extends ThemeProps, LocaleProps {
|
|||||||
collapseBtnLabel?: string;
|
collapseBtnLabel?: string;
|
||||||
popOverContainer?: any;
|
popOverContainer?: any;
|
||||||
children?: React.ReactNode | Array<React.ReactNode>;
|
children?: React.ReactNode | Array<React.ReactNode>;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDragInfo {
|
export interface IDragInfo {
|
||||||
@ -271,6 +322,29 @@ export class Tabs extends React.Component<TabsProps, any> {
|
|||||||
if (!this.scroll && !this.draging && isTabsModified) {
|
if (!this.scroll && !this.draging && isTabsModified) {
|
||||||
this.computedWidth();
|
this.computedWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 移动端取消箭头切换,改为滚动切换激活项居中
|
||||||
|
const {classPrefix: ns, activeKey, useMobileUI} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
if (mobileUI && preProps.activeKey !== activeKey) {
|
||||||
|
const {classPrefix: ns} = this.props;
|
||||||
|
const dom = findDOMNode(this) as HTMLElement;
|
||||||
|
const activeTab = dom.querySelector(
|
||||||
|
`.${ns}Tabs-link.is-active`
|
||||||
|
) as HTMLElement;
|
||||||
|
const parentWidth = (activeTab.parentNode?.parentNode as any).offsetWidth;
|
||||||
|
const offsetLeft = activeTab.offsetLeft;
|
||||||
|
const offsetWidth = activeTab.offsetWidth;
|
||||||
|
if (activeTab.parentNode) {
|
||||||
|
(activeTab.parentNode as any).scrollLeft =
|
||||||
|
offsetLeft > parentWidth
|
||||||
|
? (offsetLeft / parentWidth) * parentWidth -
|
||||||
|
parentWidth / 2 +
|
||||||
|
offsetWidth / 2
|
||||||
|
: offsetLeft - parentWidth / 2 + offsetWidth / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.scroll = false;
|
this.scroll = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,9 +834,11 @@ export class Tabs extends React.Component<TabsProps, any> {
|
|||||||
addable,
|
addable,
|
||||||
draggable,
|
draggable,
|
||||||
sidePosition,
|
sidePosition,
|
||||||
addBtnText
|
addBtnText,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
const {isOverflow} = this.state;
|
const {isOverflow} = this.state;
|
||||||
if (!Array.isArray(children)) {
|
if (!Array.isArray(children)) {
|
||||||
return null;
|
return null;
|
||||||
@ -811,10 +887,12 @@ export class Tabs extends React.Component<TabsProps, any> {
|
|||||||
isOverflow && 'Tabs-linksContainer--overflow'
|
isOverflow && 'Tabs-linksContainer--overflow'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{this.renderArrow('left')}
|
{!mobileUI ? this.renderArrow('left') : null}
|
||||||
<div className={cx('Tabs-linksContainer-main')}>
|
<div className={cx('Tabs-linksContainer-main')}>
|
||||||
<ul
|
<ul
|
||||||
className={cx('Tabs-links', linksClassName)}
|
className={cx('Tabs-links', linksClassName, {
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
})}
|
||||||
role="tablist"
|
role="tablist"
|
||||||
ref={this.navMain}
|
ref={this.navMain}
|
||||||
>
|
>
|
||||||
@ -823,13 +901,18 @@ export class Tabs extends React.Component<TabsProps, any> {
|
|||||||
{!isOverflow && toolButtons}
|
{!isOverflow && toolButtons}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{this.renderArrow('right')}
|
{!mobileUI ? this.renderArrow('right') : null}
|
||||||
</div>
|
</div>
|
||||||
{isOverflow && toolButtons}
|
{isOverflow && toolButtons}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={cx('Tabs-linksWrapper')}>
|
<div className={cx('Tabs-linksWrapper')}>
|
||||||
<ul className={cx('Tabs-links', linksClassName)} role="tablist">
|
<ul
|
||||||
|
className={cx('Tabs-links', linksClassName, {
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
})}
|
||||||
|
role="tablist"
|
||||||
|
>
|
||||||
{this.renderNavs()}
|
{this.renderNavs()}
|
||||||
{additionBtns}
|
{additionBtns}
|
||||||
{toolbar}
|
{toolbar}
|
||||||
|
@ -15,6 +15,7 @@ import {ItemRenderStates} from './Selection';
|
|||||||
import {Icon} from './icons';
|
import {Icon} from './icons';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import {SpinnerExtraProps} from './Spinner';
|
import {SpinnerExtraProps} from './Spinner';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
export interface TabsTransferProps
|
export interface TabsTransferProps
|
||||||
extends Omit<
|
extends Omit<
|
||||||
@ -51,6 +52,7 @@ export interface TabsTransferProps
|
|||||||
activeKey: number;
|
activeKey: number;
|
||||||
onlyChildren?: boolean;
|
onlyChildren?: boolean;
|
||||||
ctx?: Record<string, any>;
|
ctx?: Record<string, any>;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TabsTransferState {
|
export interface TabsTransferState {
|
||||||
@ -266,9 +268,11 @@ export class TabsTransfer extends React.Component<
|
|||||||
activeKey,
|
activeKey,
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
translate: __,
|
translate: __,
|
||||||
ctx
|
ctx,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const showOptions = options.filter(item => item.visible !== false);
|
const showOptions = options.filter(item => item.visible !== false);
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
if (!Array.isArray(options) || !options.length) {
|
if (!Array.isArray(options) || !options.length) {
|
||||||
return (
|
return (
|
||||||
@ -296,7 +300,9 @@ export class TabsTransfer extends React.Component<
|
|||||||
className="TabsTransfer-tab"
|
className="TabsTransfer-tab"
|
||||||
>
|
>
|
||||||
{option.searchable ? (
|
{option.searchable ? (
|
||||||
<div className={cx('TabsTransfer-search')}>
|
<div
|
||||||
|
className={cx('TabsTransfer-search', {'is-mobile': mobileUI})}
|
||||||
|
>
|
||||||
<InputBox
|
<InputBox
|
||||||
value={this.state.inputValue}
|
value={this.state.inputValue}
|
||||||
onChange={(text: string) => this.handleSearch(text, option)}
|
onChange={(text: string) => this.handleSearch(text, option)}
|
||||||
@ -478,12 +484,14 @@ export class TabsTransfer extends React.Component<
|
|||||||
classnames: cx,
|
classnames: cx,
|
||||||
optionItemRender,
|
optionItemRender,
|
||||||
onSearch,
|
onSearch,
|
||||||
|
useMobileUI,
|
||||||
...reset
|
...reset
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Transfer
|
<Transfer
|
||||||
{...reset}
|
{...reset}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
statistics={false}
|
statistics={false}
|
||||||
classnames={cx}
|
classnames={cx}
|
||||||
className={cx('TabsTransfer', className)}
|
className={cx('TabsTransfer', className)}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {localeable} from 'amis-core';
|
import {isMobile, localeable} from 'amis-core';
|
||||||
import {themeable} from 'amis-core';
|
import {themeable} from 'amis-core';
|
||||||
import {uncontrollable} from 'amis-core';
|
import {uncontrollable} from 'amis-core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -14,6 +14,7 @@ export interface TabsTransferPickerProps
|
|||||||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
||||||
onFocus?: () => void;
|
onFocus?: () => void;
|
||||||
onBlur?: () => void;
|
onBlur?: () => void;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TransferPicker extends React.Component<TabsTransferPickerProps> {
|
export class TransferPicker extends React.Component<TabsTransferPickerProps> {
|
||||||
@ -45,12 +46,15 @@ export class TransferPicker extends React.Component<TabsTransferPickerProps> {
|
|||||||
onChange,
|
onChange,
|
||||||
size,
|
size,
|
||||||
labelField = 'label',
|
labelField = 'label',
|
||||||
|
useMobileUI,
|
||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PickerContainer
|
<PickerContainer
|
||||||
title={__('Select.placeholder')}
|
title={__('Select.placeholder')}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
onFocus={this.onFoucs}
|
onFocus={this.onFoucs}
|
||||||
onClose={this.onBlur}
|
onClose={this.onBlur}
|
||||||
bodyRender={({onClose, value, onChange, setState, ...states}) => {
|
bodyRender={({onClose, value, onChange, setState, ...states}) => {
|
||||||
@ -59,6 +63,7 @@ export class TransferPicker extends React.Component<TabsTransferPickerProps> {
|
|||||||
{...rest}
|
{...rest}
|
||||||
{...states}
|
{...states}
|
||||||
value={value}
|
value={value}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
onChange={(value: any, optionModified) => {
|
onChange={(value: any, optionModified) => {
|
||||||
if (optionModified) {
|
if (optionModified) {
|
||||||
let options = mapTree(rest.options, item => {
|
let options = mapTree(rest.options, item => {
|
||||||
@ -96,10 +101,13 @@ export class TransferPicker extends React.Component<TabsTransferPickerProps> {
|
|||||||
itemRender={option => (
|
itemRender={option => (
|
||||||
<span>{(option && option[labelField]) || 'undefiend'}</span>
|
<span>{(option && option[labelField]) || 'undefiend'}</span>
|
||||||
)}
|
)}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
>
|
>
|
||||||
<span className={cx('TransferPicker-icon')}>
|
{!mobileUI ? (
|
||||||
<Icon icon="pencil" className="icon" />
|
<span className={cx('TransferPicker-icon')}>
|
||||||
</span>
|
<Icon icon="pencil" className="icon" />
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
</ResultBox>
|
</ResultBox>
|
||||||
)}
|
)}
|
||||||
</PickerContainer>
|
</PickerContainer>
|
||||||
|
@ -60,6 +60,7 @@ export interface TextAreaProps extends ThemeProps, LocaleProps {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
||||||
forwardRef?: {current: HTMLTextAreaElement | null};
|
forwardRef?: {current: HTMLTextAreaElement | null};
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TextAreaState {
|
export interface TextAreaState {
|
||||||
|
@ -13,6 +13,7 @@ import {ThemeProps, themeable, findTree} from 'amis-core';
|
|||||||
import {BaseSelectionProps, BaseSelection, ItemRenderStates} from './Selection';
|
import {BaseSelectionProps, BaseSelection, ItemRenderStates} from './Selection';
|
||||||
import {Options, Option} from './Select';
|
import {Options, Option} from './Select';
|
||||||
import {uncontrollable} from 'amis-core';
|
import {uncontrollable} from 'amis-core';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
import ResultList from './ResultList';
|
import ResultList from './ResultList';
|
||||||
import TableSelection from './TableSelection';
|
import TableSelection from './TableSelection';
|
||||||
import {autobind, flattenTree} from 'amis-core';
|
import {autobind, flattenTree} from 'amis-core';
|
||||||
@ -115,9 +116,11 @@ export interface TransferProps
|
|||||||
checkAllLabel?: string;
|
checkAllLabel?: string;
|
||||||
/** 树形模式下,给 tree 的属性 */
|
/** 树形模式下,给 tree 的属性 */
|
||||||
onlyChildren?: boolean;
|
onlyChildren?: boolean;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransferState {
|
export interface TransferState {
|
||||||
|
tempValue?: Array<Option> | Option;
|
||||||
inputValue: string;
|
inputValue: string;
|
||||||
searchResult: Options | null;
|
searchResult: Options | null;
|
||||||
isTreeDeferLoad: boolean;
|
isTreeDeferLoad: boolean;
|
||||||
@ -366,7 +369,8 @@ export class Transfer<
|
|||||||
options,
|
options,
|
||||||
statistics,
|
statistics,
|
||||||
translate: __,
|
translate: __,
|
||||||
searchPlaceholder = __('Transfer.searchKeyword')
|
searchPlaceholder = __('Transfer.searchKeyword'),
|
||||||
|
useMobileUI
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
if (selectRender) {
|
if (selectRender) {
|
||||||
@ -395,6 +399,8 @@ export class Transfer<
|
|||||||
isEqual
|
isEqual
|
||||||
).length;
|
).length;
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
@ -437,7 +443,7 @@ export class Transfer<
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{onSearch ? (
|
{onSearch ? (
|
||||||
<div className={cx('Transfer-search')}>
|
<div className={cx('Transfer-search', {'is-mobile': mobileUI})}>
|
||||||
<InputBox
|
<InputBox
|
||||||
value={this.state.inputValue}
|
value={this.state.inputValue}
|
||||||
onChange={this.handleSearch}
|
onChange={this.handleSearch}
|
||||||
@ -818,7 +824,8 @@ export class Transfer<
|
|||||||
resultListModeFollowSelect,
|
resultListModeFollowSelect,
|
||||||
selectMode = 'list',
|
selectMode = 'list',
|
||||||
translate: __,
|
translate: __,
|
||||||
valueField = 'value'
|
valueField = 'value',
|
||||||
|
useMobileUI
|
||||||
} = this.props as any;
|
} = this.props as any;
|
||||||
const {searchResult} = this.state;
|
const {searchResult} = this.state;
|
||||||
|
|
||||||
@ -832,6 +839,7 @@ export class Transfer<
|
|||||||
);
|
);
|
||||||
|
|
||||||
const tableType = resultListModeFollowSelect && selectMode === 'table';
|
const tableType = resultListModeFollowSelect && selectMode === 'table';
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -847,7 +855,7 @@ export class Transfer<
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div className={cx('Transfer-result')}>
|
<div className={cx('Transfer-result', {'is-mobile': mobileUI})}>
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
'Transfer-title',
|
'Transfer-title',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {localeable} from 'amis-core';
|
import {localeable} from 'amis-core';
|
||||||
import {themeable} from 'amis-core';
|
import {themeable} from 'amis-core';
|
||||||
import {Transfer, TransferProps} from './Transfer';
|
import {Transfer, TransferProps, TransferState} from './Transfer';
|
||||||
import {uncontrollable, autobind} from 'amis-core';
|
import {uncontrollable, autobind} from 'amis-core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ResultBox from './ResultBox';
|
import ResultBox from './ResultBox';
|
||||||
@ -29,11 +29,51 @@ export interface TransferDropDownProps extends TransferProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TransferDropDown extends Transfer<TransferDropDownProps> {
|
export class TransferDropDown extends Transfer<TransferDropDownProps> {
|
||||||
|
constructor(props: TransferDropDownProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
tempValue: props.value,
|
||||||
|
inputValue: '',
|
||||||
|
searchResult: null,
|
||||||
|
isTreeDeferLoad: false,
|
||||||
|
resultSelectMode: 'list'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: TransferDropDownProps) {
|
||||||
|
if (this.props.value !== prevProps.value) {
|
||||||
|
this.setState({
|
||||||
|
tempValue: this.props.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleAfterPopoverHide() {
|
handleAfterPopoverHide() {
|
||||||
this.setState({inputValue: '', searchResult: null});
|
this.setState({inputValue: '', searchResult: null});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handleChange(value: any, onClose: () => void) {
|
||||||
|
const {multiple, onChange, useMobileUI} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
|
if (mobileUI) {
|
||||||
|
this.setState({tempValue: value});
|
||||||
|
} else {
|
||||||
|
onChange?.(value);
|
||||||
|
if (!multiple) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
onConfirm() {
|
||||||
|
const {onChange} = this.props;
|
||||||
|
onChange?.(this.state.tempValue as typeof Option[]);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
@ -68,6 +108,8 @@ export class TransferDropDown extends Transfer<TransferDropDownProps> {
|
|||||||
overlayWidth={overlay && overlay?.width}
|
overlayWidth={overlay && overlay?.width}
|
||||||
align={overlay && overlay?.align}
|
align={overlay && overlay?.align}
|
||||||
popOverClassName={cx('TransferDropDown-popover')}
|
popOverClassName={cx('TransferDropDown-popover')}
|
||||||
|
showConfirm
|
||||||
|
onConfirm={this.onConfirm}
|
||||||
popOverRender={({onClose}) => (
|
popOverRender={({onClose}) => (
|
||||||
<div
|
<div
|
||||||
className={cx('TransferDropDown-content', {
|
className={cx('TransferDropDown-content', {
|
||||||
@ -96,24 +138,14 @@ export class TransferDropDown extends Transfer<TransferDropDownProps> {
|
|||||||
{searchResult !== null
|
{searchResult !== null
|
||||||
? this.renderSearchResult({
|
? this.renderSearchResult({
|
||||||
...this.props,
|
...this.props,
|
||||||
value,
|
value: this.state.tempValue,
|
||||||
onChange: multiple
|
onChange: value => this.handleChange(value, onClose),
|
||||||
? onChange
|
|
||||||
: (value: any) => {
|
|
||||||
onClose();
|
|
||||||
onChange?.(value);
|
|
||||||
},
|
|
||||||
multiple
|
multiple
|
||||||
})
|
})
|
||||||
: this.renderOptions({
|
: this.renderOptions({
|
||||||
...this.props,
|
...this.props,
|
||||||
value,
|
value: this.state.tempValue,
|
||||||
onChange: multiple
|
onChange: value => this.handleChange(value, onClose),
|
||||||
? onChange
|
|
||||||
: (value: any) => {
|
|
||||||
onClose();
|
|
||||||
onChange?.(value);
|
|
||||||
},
|
|
||||||
multiple
|
multiple
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,7 +6,7 @@ import React from 'react';
|
|||||||
import ResultBox from './ResultBox';
|
import ResultBox from './ResultBox';
|
||||||
import {Icon} from './icons';
|
import {Icon} from './icons';
|
||||||
import PickerContainer from './PickerContainer';
|
import PickerContainer from './PickerContainer';
|
||||||
import {autobind, mapTree} from 'amis-core';
|
import {autobind, mapTree, isMobile} from 'amis-core';
|
||||||
|
|
||||||
export interface TransferPickerProps extends Omit<TransferProps, 'itemRender'> {
|
export interface TransferPickerProps extends Omit<TransferProps, 'itemRender'> {
|
||||||
// 新的属性?
|
// 新的属性?
|
||||||
@ -20,6 +20,7 @@ export interface TransferPickerProps extends Omit<TransferProps, 'itemRender'> {
|
|||||||
onFocus?: () => void;
|
onFocus?: () => void;
|
||||||
|
|
||||||
onBlur?: () => void;
|
onBlur?: () => void;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TransferPicker extends React.Component<TransferPickerProps> {
|
export class TransferPicker extends React.Component<TransferPickerProps> {
|
||||||
@ -51,17 +52,21 @@ export class TransferPicker extends React.Component<TransferPickerProps> {
|
|||||||
size,
|
size,
|
||||||
borderMode,
|
borderMode,
|
||||||
labelField = 'label',
|
labelField = 'label',
|
||||||
|
useMobileUI,
|
||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PickerContainer
|
<PickerContainer
|
||||||
title={__('Select.placeholder')}
|
title={__('Select.placeholder')}
|
||||||
onFocus={this.onFoucs}
|
onFocus={this.onFoucs}
|
||||||
onClose={this.onBlur}
|
onClose={this.onBlur}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
bodyRender={({onClose, value, onChange, setState, ...states}) => {
|
bodyRender={({onClose, value, onChange, setState, ...states}) => {
|
||||||
return (
|
return (
|
||||||
<Transfer
|
<Transfer
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
{...rest}
|
{...rest}
|
||||||
{...states}
|
{...states}
|
||||||
value={value}
|
value={value}
|
||||||
@ -103,10 +108,13 @@ export class TransferPicker extends React.Component<TransferPickerProps> {
|
|||||||
itemRender={option => (
|
itemRender={option => (
|
||||||
<span>{(option && option[labelField]) || 'undefined'}</span>
|
<span>{(option && option[labelField]) || 'undefined'}</span>
|
||||||
)}
|
)}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
>
|
>
|
||||||
<span className={cx('TransferPicker-icon')}>
|
{!mobileUI ? (
|
||||||
<Icon icon="pencil" className="icon" />
|
<span className={cx('TransferPicker-icon')}>
|
||||||
</span>
|
<Icon icon="pencil" className="icon" />
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
</ResultBox>
|
</ResultBox>
|
||||||
)}
|
)}
|
||||||
</PickerContainer>
|
</PickerContainer>
|
||||||
|
@ -32,7 +32,7 @@ import {Option, Options, value2array} from './Select';
|
|||||||
import {themeable, ThemeProps, highlight} from 'amis-core';
|
import {themeable, ThemeProps, highlight} from 'amis-core';
|
||||||
import {Icon, getIcon} from './icons';
|
import {Icon, getIcon} from './icons';
|
||||||
import Checkbox from './Checkbox';
|
import Checkbox from './Checkbox';
|
||||||
import {LocaleProps, localeable} from 'amis-core';
|
import {LocaleProps, localeable, isMobile} from 'amis-core';
|
||||||
import Spinner, {SpinnerExtraProps} from './Spinner';
|
import Spinner, {SpinnerExtraProps} from './Spinner';
|
||||||
import {ItemRenderStates} from './Selection';
|
import {ItemRenderStates} from './Selection';
|
||||||
import VirtualList from './virtual-list';
|
import VirtualList from './virtual-list';
|
||||||
@ -149,6 +149,7 @@ interface TreeSelectorProps extends ThemeProps, LocaleProps, SpinnerExtraProps {
|
|||||||
// 全选按钮文案
|
// 全选按钮文案
|
||||||
checkAllLabel?: string;
|
checkAllLabel?: string;
|
||||||
enableDefaultIcon?: boolean;
|
enableDefaultIcon?: boolean;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TreeSelectorState {
|
interface TreeSelectorState {
|
||||||
@ -716,12 +717,21 @@ export class TreeSelector extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderInput(prfix: JSX.Element | null = null) {
|
renderInput(prfix: JSX.Element | null = null) {
|
||||||
const {classnames: cx, translate: __} = this.props;
|
const {classnames: cx, useMobileUI, translate: __} = this.props;
|
||||||
const {inputValue} = this.state;
|
const {inputValue} = this.state;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx('Tree-itemLabel')}>
|
<div
|
||||||
<div className={cx('Tree-itemInput')}>
|
className={cx('Tree-itemLabel', {
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={cx('Tree-itemInput', {
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
})}
|
||||||
|
>
|
||||||
{prfix}
|
{prfix}
|
||||||
<input
|
<input
|
||||||
onChange={this.handleInputChange}
|
onChange={this.handleInputChange}
|
||||||
@ -1064,9 +1074,11 @@ export class TreeSelector extends React.Component<
|
|||||||
draggable,
|
draggable,
|
||||||
loadingConfig,
|
loadingConfig,
|
||||||
enableDefaultIcon,
|
enableDefaultIcon,
|
||||||
valueField
|
valueField,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
const item = this.state.flattenedOptions[index];
|
const item = this.state.flattenedOptions[index];
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
@ -1160,7 +1172,7 @@ export class TreeSelector extends React.Component<
|
|||||||
|
|
||||||
{checkbox}
|
{checkbox}
|
||||||
|
|
||||||
<div className={cx('Tree-itemLabel-item')}>
|
<div className={cx('Tree-itemLabel-item', {'is-mobile': mobileUI})}>
|
||||||
{showIcon ? (
|
{showIcon ? (
|
||||||
<i
|
<i
|
||||||
className={cx(
|
className={cx(
|
||||||
@ -1308,7 +1320,8 @@ export class TreeSelector extends React.Component<
|
|||||||
checkAllLabel,
|
checkAllLabel,
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
translate: __,
|
translate: __,
|
||||||
disabled
|
disabled,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!multiple || !checkAll) {
|
if (!multiple || !checkAll) {
|
||||||
@ -1323,6 +1336,7 @@ export class TreeSelector extends React.Component<
|
|||||||
const checkedPartial = availableOptions.some(option =>
|
const checkedPartial = availableOptions.some(option =>
|
||||||
this.isItemChecked(option)
|
this.isItemChecked(option)
|
||||||
);
|
);
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -1336,7 +1350,11 @@ export class TreeSelector extends React.Component<
|
|||||||
partial={checkedPartial && !checkedAll}
|
partial={checkedPartial && !checkedAll}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={cx('Tree-itemLabel-item')}>
|
<div
|
||||||
|
className={cx('Tree-itemLabel-item', {
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
})}
|
||||||
|
>
|
||||||
<span className={cx('Tree-itemText')}>{__(checkAllLabel)}</span>
|
<span className={cx('Tree-itemText')}>{__(checkAllLabel)}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
import {PickerOption} from '../PickerColumn';
|
import {PickerOption} from '../PickerColumn';
|
||||||
import 'moment/locale/zh-cn';
|
import 'moment/locale/zh-cn';
|
||||||
import 'moment/locale/de';
|
import 'moment/locale/de';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
export type DateType =
|
export type DateType =
|
||||||
| 'year'
|
| 'year'
|
||||||
@ -690,6 +691,8 @@ class BaseDatePicker extends React.Component<
|
|||||||
key="dt"
|
key="dt"
|
||||||
className={cx(
|
className={cx(
|
||||||
'rdtPicker',
|
'rdtPicker',
|
||||||
|
{'is-mobile-year': isMobile() && viewMode === 'years'},
|
||||||
|
{'is-mobile-embed': isMobile() && viewProps.embed},
|
||||||
timeFormat && !dateFormat
|
timeFormat && !dateFormat
|
||||||
? 'rdtPickerTimeWithoutD'
|
? 'rdtPickerTimeWithoutD'
|
||||||
: timeFormat && dateFormat
|
: timeFormat && dateFormat
|
||||||
|
@ -683,9 +683,11 @@ export class CustomTimeView extends React.Component<
|
|||||||
<div
|
<div
|
||||||
key={option.value}
|
key={option.value}
|
||||||
className={cx('CalendarInput-sugsItem', {
|
className={cx('CalendarInput-sugsItem', {
|
||||||
|
'is-mobile': isMobile(),
|
||||||
'is-highlight': selectedDate
|
'is-highlight': selectedDate
|
||||||
? option.value === date.format(formatMap[type])
|
? option.value === date.format(formatMap[type])
|
||||||
: option.value === options?.[0]?.value
|
: option.value === options?.[0]?.value &&
|
||||||
|
!isMobile()
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.setTime(type, parseInt(option.value, 10));
|
this.setTime(type, parseInt(option.value, 10));
|
||||||
|
@ -22,6 +22,7 @@ import FuncList from './FuncList';
|
|||||||
import VariableList from './VariableList';
|
import VariableList from './VariableList';
|
||||||
import CodeMirrorEditor from '../CodeMirror';
|
import CodeMirrorEditor from '../CodeMirror';
|
||||||
import {toast} from '../Toast';
|
import {toast} from '../Toast';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
export interface VariableItem {
|
export interface VariableItem {
|
||||||
label: string;
|
label: string;
|
||||||
@ -358,7 +359,9 @@ export class FormulaEditor extends React.Component<
|
|||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className={cx('FormulaEditor-settings')}>
|
<section
|
||||||
|
className={cx('FormulaEditor-settings', {'is-mobile': isMobile()})}
|
||||||
|
>
|
||||||
<div className={cx('FormulaEditor-panel')}>
|
<div className={cx('FormulaEditor-panel')}>
|
||||||
{variableMode !== 'tabs' ? (
|
{variableMode !== 'tabs' ? (
|
||||||
<div className={cx('FormulaEditor-panel-header')}>
|
<div className={cx('FormulaEditor-panel-header')}>
|
||||||
|
@ -44,7 +44,7 @@ export function FuncList(props: FuncListProps) {
|
|||||||
<div className={cx('FormulaEditor-panel-header')}>{title}</div>
|
<div className={cx('FormulaEditor-panel-header')}>{title}</div>
|
||||||
<div className={cx('FormulaEditor-panel-body')}>
|
<div className={cx('FormulaEditor-panel-body')}>
|
||||||
<div className={cx('FormulaEditor-FuncList-searchBox')}>
|
<div className={cx('FormulaEditor-FuncList-searchBox')}>
|
||||||
<SearchBox mini={false} onSearch={onSearch} />
|
<SearchBox mini={false} onSearch={onSearch} useMobileUI />
|
||||||
</div>
|
</div>
|
||||||
<div className={cx('FormulaEditor-FuncList-body', bodyClassName)}>
|
<div className={cx('FormulaEditor-FuncList-body', bodyClassName)}>
|
||||||
<CollapseGroup
|
<CollapseGroup
|
||||||
|
@ -20,7 +20,8 @@ import ResultBox from '../ResultBox';
|
|||||||
import Button from '../Button';
|
import Button from '../Button';
|
||||||
import {Icon} from '../icons';
|
import {Icon} from '../icons';
|
||||||
import Modal from '../Modal';
|
import Modal from '../Modal';
|
||||||
import Input from '../Input';
|
import PopUp from '../PopUp';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
export interface FormulaPickerProps extends FormulaEditorProps {
|
export interface FormulaPickerProps extends FormulaEditorProps {
|
||||||
// 新的属性?
|
// 新的属性?
|
||||||
@ -123,6 +124,7 @@ export interface FormulaPickerProps extends FormulaEditorProps {
|
|||||||
onRef?: (node: any) => void;
|
onRef?: (node: any) => void;
|
||||||
|
|
||||||
popOverContainer?: any;
|
popOverContainer?: any;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormulaPickerState {
|
export interface FormulaPickerState {
|
||||||
@ -333,10 +335,12 @@ export class FormulaPicker extends React.Component<
|
|||||||
mixedMode,
|
mixedMode,
|
||||||
evalMode,
|
evalMode,
|
||||||
popOverContainer,
|
popOverContainer,
|
||||||
|
useMobileUI,
|
||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {isOpened, value, editorValue, isError} = this.state;
|
const {isOpened, value, editorValue, isError} = this.state;
|
||||||
const iconElement = generateIcon(cx, icon, 'Icon');
|
const iconElement = generateIcon(cx, icon, 'Icon');
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -411,6 +415,8 @@ export class FormulaPicker extends React.Component<
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
borderMode={borderMode}
|
borderMode={borderMode}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
|
showArrow={false}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@ -452,6 +458,8 @@ export class FormulaPicker extends React.Component<
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
borderMode={borderMode}
|
borderMode={borderMode}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
|
showArrow={false}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
@ -464,42 +472,72 @@ export class FormulaPicker extends React.Component<
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Modal
|
{mobileUI ? (
|
||||||
size="md"
|
<PopUp
|
||||||
closeOnEsc
|
className={cx(`FormulaPicker-popup`)}
|
||||||
show={this.state.isOpened}
|
isShow={this.state.isOpened}
|
||||||
onHide={this.close}
|
showConfirm
|
||||||
container={popOverContainer}
|
onHide={this.close}
|
||||||
>
|
onConfirm={this.handleEditorConfirm}
|
||||||
<Modal.Header onClose={this.close} className="font-bold">
|
>
|
||||||
{__(title || 'FormulaEditor.title')}
|
<div className={cx('FormulaPicker-popup-inner')}>
|
||||||
</Modal.Header>
|
<Editor
|
||||||
<Modal.Body>
|
{...rest}
|
||||||
<Editor
|
evalMode={mixedMode ? true : evalMode}
|
||||||
{...rest}
|
variables={this.state.variables ?? variables}
|
||||||
evalMode={mixedMode ? true : evalMode}
|
functions={this.state.functions ?? functions}
|
||||||
variables={this.state.variables ?? variables}
|
variableMode={this.state.variableMode ?? variableMode}
|
||||||
functions={this.state.functions ?? functions}
|
value={editorValue}
|
||||||
variableMode={this.state.variableMode ?? variableMode}
|
onChange={this.handleEditorChange}
|
||||||
value={editorValue}
|
selfVariableName={this.props.selfVariableName}
|
||||||
onChange={this.handleEditorChange}
|
/>
|
||||||
selfVariableName={this.props.selfVariableName}
|
{!!isError ? (
|
||||||
/>
|
<div className={cx('Dialog-info')} key="info">
|
||||||
</Modal.Body>
|
<span className={cx('Dialog-error')}>
|
||||||
<Modal.Footer>
|
{__('FormulaEditor.invalidData', {err: isError})}
|
||||||
{!!isError ? (
|
</span>
|
||||||
<div className={cx('Dialog-info')} key="info">
|
</div>
|
||||||
<span className={cx('Dialog-error')}>
|
) : null}
|
||||||
{__('FormulaEditor.invalidData', {err: isError})}
|
</div>
|
||||||
</span>
|
</PopUp>
|
||||||
</div>
|
) : (
|
||||||
) : null}
|
<Modal
|
||||||
<Button onClick={this.close}>{__('cancel')}</Button>
|
size="md"
|
||||||
<Button onClick={this.handleEditorConfirm} level="primary">
|
closeOnEsc
|
||||||
{__('confirm')}
|
show={this.state.isOpened}
|
||||||
</Button>
|
onHide={this.close}
|
||||||
</Modal.Footer>
|
container={popOverContainer}
|
||||||
</Modal>
|
>
|
||||||
|
<Modal.Header onClose={this.close} className="font-bold">
|
||||||
|
{__(title || 'FormulaEditor.title')}
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<Editor
|
||||||
|
{...rest}
|
||||||
|
evalMode={mixedMode ? true : evalMode}
|
||||||
|
variables={this.state.variables ?? variables}
|
||||||
|
functions={this.state.functions ?? functions}
|
||||||
|
variableMode={this.state.variableMode ?? variableMode}
|
||||||
|
value={editorValue}
|
||||||
|
onChange={this.handleEditorChange}
|
||||||
|
selfVariableName={this.props.selfVariableName}
|
||||||
|
/>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
{!!isError ? (
|
||||||
|
<div className={cx('Dialog-info')} key="info">
|
||||||
|
<span className={cx('Dialog-error')}>
|
||||||
|
{__('FormulaEditor.invalidData', {err: isError})}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<Button onClick={this.close}>{__('cancel')}</Button>
|
||||||
|
<Button onClick={this.handleEditorConfirm} level="primary">
|
||||||
|
{__('confirm')}
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ function VariableList(props: VariableListProps) {
|
|||||||
function renderSearchBox() {
|
function renderSearchBox() {
|
||||||
return (
|
return (
|
||||||
<div className={cx('FormulaEditor-VariableList-searchBox')}>
|
<div className={cx('FormulaEditor-VariableList-searchBox')}>
|
||||||
<SearchBox mini={false} onSearch={onSearch} />
|
<SearchBox mini={false} onSearch={onSearch} useMobileUI />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import Button from '../Button';
|
|||||||
import {Icon} from '../icons';
|
import {Icon} from '../icons';
|
||||||
import type {InputJSONSchemaItemProps} from './index';
|
import type {InputJSONSchemaItemProps} from './index';
|
||||||
import {InputJSONSchemaItem} from './Item';
|
import {InputJSONSchemaItem} from './Item';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
type JSONSchemaArrayMember = {
|
type JSONSchemaArrayMember = {
|
||||||
key: string;
|
key: string;
|
||||||
@ -19,7 +20,8 @@ export function InputJSONSchemaArray(props: InputJSONSchemaItemProps) {
|
|||||||
disabled,
|
disabled,
|
||||||
translate: __,
|
translate: __,
|
||||||
collapsable,
|
collapsable,
|
||||||
renderValue
|
renderValue,
|
||||||
|
useMobileUI
|
||||||
} = props;
|
} = props;
|
||||||
const buildMembers = React.useCallback((schema: any, value: any) => {
|
const buildMembers = React.useCallback((schema: any, value: any) => {
|
||||||
const members: Array<JSONSchemaArrayMember> = [];
|
const members: Array<JSONSchemaArrayMember> = [];
|
||||||
@ -137,6 +139,7 @@ export function InputJSONSchemaArray(props: InputJSONSchemaItemProps) {
|
|||||||
// todo additionalProperties 还有其他格式
|
// todo additionalProperties 还有其他格式
|
||||||
const allowAdd = !maxContains || maxContains > members.length;
|
const allowAdd = !maxContains || maxContains > members.length;
|
||||||
const allowDelete = !minContains || minContains < members.length;
|
const allowDelete = !minContains || minContains < members.length;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -153,6 +156,7 @@ export function InputJSONSchemaArray(props: InputJSONSchemaItemProps) {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
className={cx('JSONSchemaObject', {
|
className={cx('JSONSchemaObject', {
|
||||||
|
'is-mobile': mobileUI,
|
||||||
'is-expanded': collapsable && !collapsed
|
'is-expanded': collapsable && !collapsed
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
@ -20,6 +20,7 @@ export function InputJSONSchemaItem(props: InputJSONSchemaItemProps) {
|
|||||||
value={props.value}
|
value={props.value}
|
||||||
onChange={props.onChange}
|
onChange={props.onChange}
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
|
useMobileUI={props.useMobileUI}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (schema.type == 'integer') {
|
} else if (schema.type == 'integer') {
|
||||||
@ -29,6 +30,7 @@ export function InputJSONSchemaItem(props: InputJSONSchemaItemProps) {
|
|||||||
onChange={props.onChange}
|
onChange={props.onChange}
|
||||||
precision={0}
|
precision={0}
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
|
useMobileUI={props.useMobileUI}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (schema.type == 'boolean') {
|
} else if (schema.type == 'boolean') {
|
||||||
@ -42,6 +44,7 @@ export function InputJSONSchemaItem(props: InputJSONSchemaItemProps) {
|
|||||||
value={props.value}
|
value={props.value}
|
||||||
onChange={props.onChange}
|
onChange={props.onChange}
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
|
useMobileUI={props.useMobileUI}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import InputBoxWithSuggestion from '../InputBoxWithSuggestion';
|
|||||||
import Select from '../Select';
|
import Select from '../Select';
|
||||||
import type {InputJSONSchemaItemProps} from './index';
|
import type {InputJSONSchemaItemProps} from './index';
|
||||||
import {InputJSONSchemaItem} from './Item';
|
import {InputJSONSchemaItem} from './Item';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
type JSONSchemaObjectMember = {
|
type JSONSchemaObjectMember = {
|
||||||
key: string;
|
key: string;
|
||||||
@ -25,7 +26,8 @@ export function InputJSONSchemaObject(props: InputJSONSchemaItemProps) {
|
|||||||
translate: __,
|
translate: __,
|
||||||
renderKey,
|
renderKey,
|
||||||
collapsable,
|
collapsable,
|
||||||
renderValue
|
renderValue,
|
||||||
|
useMobileUI
|
||||||
} = props;
|
} = props;
|
||||||
const buildMembers = React.useCallback((schema: any, value: any) => {
|
const buildMembers = React.useCallback((schema: any, value: any) => {
|
||||||
const members: Array<JSONSchemaObjectMember> = [];
|
const members: Array<JSONSchemaObjectMember> = [];
|
||||||
@ -189,6 +191,7 @@ export function InputJSONSchemaObject(props: InputJSONSchemaItemProps) {
|
|||||||
options.every(o => members.find(m => m.name === o.value))
|
options.every(o => members.find(m => m.name === o.value))
|
||||||
);
|
);
|
||||||
const allowInput = props.schema.additionalProperties !== false;
|
const allowInput = props.schema.additionalProperties !== false;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -205,6 +208,7 @@ export function InputJSONSchemaObject(props: InputJSONSchemaItemProps) {
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
className={cx('JSONSchemaObject', {
|
className={cx('JSONSchemaObject', {
|
||||||
|
'is-mobile': mobileUI,
|
||||||
'is-expanded': collapsable && !collapsed
|
'is-expanded': collapsable && !collapsed
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
@ -228,7 +232,11 @@ export function InputJSONSchemaObject(props: InputJSONSchemaItemProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={member.key} className={cx('JSONSchemaMember')}>
|
<div key={member.key} className={cx('JSONSchemaMember')}>
|
||||||
<div className={cx('JSONSchemaMember-key')}>
|
<div
|
||||||
|
className={cx('JSONSchemaMember-key', {
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
})}
|
||||||
|
>
|
||||||
{member.nameMutable ? (
|
{member.nameMutable ? (
|
||||||
<>
|
<>
|
||||||
{renderKey ? (
|
{renderKey ? (
|
||||||
@ -247,6 +255,7 @@ export function InputJSONSchemaObject(props: InputJSONSchemaItemProps) {
|
|||||||
clearable={false}
|
clearable={false}
|
||||||
placeholder={__('JSONSchema.key')}
|
placeholder={__('JSONSchema.key')}
|
||||||
options={filtedOptions}
|
options={filtedOptions}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Select
|
<Select
|
||||||
@ -258,6 +267,7 @@ export function InputJSONSchemaObject(props: InputJSONSchemaItemProps) {
|
|||||||
clearable={false}
|
clearable={false}
|
||||||
placeholder={__('JSONSchema.key')}
|
placeholder={__('JSONSchema.key')}
|
||||||
options={filtedOptions}
|
options={filtedOptions}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
@ -267,6 +277,7 @@ export function InputJSONSchemaObject(props: InputJSONSchemaItemProps) {
|
|||||||
onChange={onMemberKeyChange.bind(null, member)}
|
onChange={onMemberKeyChange.bind(null, member)}
|
||||||
clearable={false}
|
clearable={false}
|
||||||
placeholder={__('JSONSchema.key')}
|
placeholder={__('JSONSchema.key')}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -29,6 +29,7 @@ export interface InputJSONSchemaItemProps extends ThemeProps, LocaleProps {
|
|||||||
) => JSX.Element;
|
) => JSX.Element;
|
||||||
collapsable?: boolean;
|
collapsable?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InputJSONSchemaProps
|
export interface InputJSONSchemaProps
|
||||||
|
@ -41,7 +41,8 @@ export class SchemaEditorItemArray extends SchemaEditorItemCommon {
|
|||||||
onTypeChange,
|
onTypeChange,
|
||||||
enableAdvancedSetting,
|
enableAdvancedSetting,
|
||||||
popOverContainer,
|
popOverContainer,
|
||||||
placeholder
|
placeholder,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const items = value?.items || {
|
const items = value?.items || {
|
||||||
type: 'string'
|
type: 'string'
|
||||||
@ -73,6 +74,7 @@ export class SchemaEditorItemArray extends SchemaEditorItemCommon {
|
|||||||
enableAdvancedSetting={enableAdvancedSetting}
|
enableAdvancedSetting={enableAdvancedSetting}
|
||||||
popOverContainer={popOverContainer}
|
popOverContainer={popOverContainer}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -54,6 +54,7 @@ export interface SchemaEditorItemCommonProps extends LocaleProps, ThemeProps {
|
|||||||
/** 各属性输入控件的placeholder */
|
/** 各属性输入控件的placeholder */
|
||||||
placeholder?: SchemaEditorItemPlaceholder;
|
placeholder?: SchemaEditorItemPlaceholder;
|
||||||
popOverContainer?: any;
|
popOverContainer?: any;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SchemaEditorItemCommon<
|
export class SchemaEditorItemCommon<
|
||||||
@ -102,7 +103,8 @@ export class SchemaEditorItemCommon<
|
|||||||
prefix,
|
prefix,
|
||||||
affix,
|
affix,
|
||||||
types,
|
types,
|
||||||
placeholder
|
placeholder,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -118,6 +120,7 @@ export class SchemaEditorItemCommon<
|
|||||||
clearable={false}
|
clearable={false}
|
||||||
disabled={disabled || typeMutable === false}
|
disabled={disabled || typeMutable === false}
|
||||||
simpleValue
|
simpleValue
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
@ -135,6 +138,7 @@ export class SchemaEditorItemCommon<
|
|||||||
|
|
||||||
{enableAdvancedSetting ? (
|
{enableAdvancedSetting ? (
|
||||||
<PickerContainer
|
<PickerContainer
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
value={value}
|
value={value}
|
||||||
bodyRender={({isOpened, value, onChange, ref}) => {
|
bodyRender={({isOpened, value, onChange, ref}) => {
|
||||||
return isOpened ? (
|
return isOpened ? (
|
||||||
@ -152,6 +156,7 @@ export class SchemaEditorItemCommon<
|
|||||||
{...field}
|
{...field}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
placeholder={__(placeholder?.title ?? '')}
|
placeholder={__(placeholder?.title ?? '')}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -164,6 +169,7 @@ export class SchemaEditorItemCommon<
|
|||||||
<Textarea
|
<Textarea
|
||||||
{...field}
|
{...field}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
placeholder={__(placeholder?.description ?? '')}
|
placeholder={__(placeholder?.description ?? '')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -178,6 +184,7 @@ export class SchemaEditorItemCommon<
|
|||||||
{...field}
|
{...field}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
placeholder={__(placeholder?.default ?? '')}
|
placeholder={__(placeholder?.default ?? '')}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -7,7 +7,9 @@ import {SchemaEditorItemObject} from './Object';
|
|||||||
export interface SchemaEditorItemProps
|
export interface SchemaEditorItemProps
|
||||||
extends SchemaEditorItemCommonProps,
|
extends SchemaEditorItemCommonProps,
|
||||||
LocaleProps,
|
LocaleProps,
|
||||||
ThemeProps {}
|
ThemeProps {
|
||||||
|
useMobileUI?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export class SchemaEditorItem extends React.Component<SchemaEditorItemProps> {
|
export class SchemaEditorItem extends React.Component<SchemaEditorItemProps> {
|
||||||
render() {
|
render() {
|
||||||
|
@ -199,7 +199,8 @@ export class SchemaEditorItemObject extends SchemaEditorItemCommon<
|
|||||||
onTypeChange,
|
onTypeChange,
|
||||||
enableAdvancedSetting,
|
enableAdvancedSetting,
|
||||||
popOverContainer,
|
popOverContainer,
|
||||||
placeholder
|
placeholder,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const members = this.state.members;
|
const members = this.state.members;
|
||||||
|
|
||||||
@ -212,6 +213,7 @@ export class SchemaEditorItemObject extends SchemaEditorItemCommon<
|
|||||||
{members.length ? (
|
{members.length ? (
|
||||||
members.map((member, index) => (
|
members.map((member, index) => (
|
||||||
<SchemaEditorItem
|
<SchemaEditorItem
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
key={member.id}
|
key={member.id}
|
||||||
types={types}
|
types={types}
|
||||||
onTypeChange={onTypeChange}
|
onTypeChange={onTypeChange}
|
||||||
@ -226,6 +228,7 @@ export class SchemaEditorItemObject extends SchemaEditorItemCommon<
|
|||||||
onChange={this.handlePropKeyChange.bind(this, index)}
|
onChange={this.handlePropKeyChange.bind(this, index)}
|
||||||
placeholder={__(placeholder?.key ?? '')}
|
placeholder={__(placeholder?.key ?? '')}
|
||||||
disabled={disabled || !!value?.$ref}
|
disabled={disabled || !!value?.$ref}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<InputBox
|
<InputBox
|
||||||
@ -234,6 +237,7 @@ export class SchemaEditorItemObject extends SchemaEditorItemCommon<
|
|||||||
onChange={this.handlePropTitleChange.bind(this, index)}
|
onChange={this.handlePropTitleChange.bind(this, index)}
|
||||||
placeholder={__(placeholder?.title ?? '')}
|
placeholder={__(placeholder?.title ?? '')}
|
||||||
disabled={disabled || !!value?.$ref}
|
disabled={disabled || !!value?.$ref}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ export interface SchemaEditorProps extends LocaleProps, ThemeProps {
|
|||||||
* 各属性输入控件的占位提示文本
|
* 各属性输入控件的占位提示文本
|
||||||
*/
|
*/
|
||||||
placeholder?: SchemaEditorItemPlaceholder;
|
placeholder?: SchemaEditorItemPlaceholder;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SchemaEditor extends React.Component<SchemaEditorProps> {
|
export class SchemaEditor extends React.Component<SchemaEditorProps> {
|
||||||
@ -171,7 +172,8 @@ export class SchemaEditor extends React.Component<SchemaEditorProps> {
|
|||||||
definitions,
|
definitions,
|
||||||
enableAdvancedSetting,
|
enableAdvancedSetting,
|
||||||
popOverContainer,
|
popOverContainer,
|
||||||
placeholder
|
placeholder,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const value: JSONSchema = this.props.value || {
|
const value: JSONSchema = this.props.value || {
|
||||||
type: defaultType || 'object'
|
type: defaultType || 'object'
|
||||||
@ -231,6 +233,7 @@ export class SchemaEditor extends React.Component<SchemaEditorProps> {
|
|||||||
enableAdvancedSetting={enableAdvancedSetting}
|
enableAdvancedSetting={enableAdvancedSetting}
|
||||||
popOverContainer={popOverContainer}
|
popOverContainer={popOverContainer}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -92,6 +92,10 @@ export interface CollapseSchema extends BaseSchema {
|
|||||||
* 卡片隐藏就销毁内容。
|
* 卡片隐藏就销毁内容。
|
||||||
*/
|
*/
|
||||||
unmountOnExit?: boolean;
|
unmountOnExit?: boolean;
|
||||||
|
/**
|
||||||
|
* 标题内容分割线
|
||||||
|
*/
|
||||||
|
divideLine?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CollapseProps
|
export interface CollapseProps
|
||||||
@ -147,9 +151,13 @@ export default class Collapse extends React.Component<CollapseProps, {}> {
|
|||||||
disabled,
|
disabled,
|
||||||
collapsed,
|
collapsed,
|
||||||
propsUpdate,
|
propsUpdate,
|
||||||
onCollapse
|
onCollapse,
|
||||||
|
useMobileUI,
|
||||||
|
divideLine
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
console.log('cooooooo', divideLine);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BasicCollapse
|
<BasicCollapse
|
||||||
id={id}
|
id={id}
|
||||||
@ -194,7 +202,9 @@ export default class Collapse extends React.Component<CollapseProps, {}> {
|
|||||||
? render('body', body)
|
? render('body', body)
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
onCollapse={onCollapse}
|
onCollapse={onCollapse}
|
||||||
|
divideLine={divideLine}
|
||||||
></BasicCollapse>
|
></BasicCollapse>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,8 @@ export class CollapseGroupRender extends React.Component<
|
|||||||
body,
|
body,
|
||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
render
|
render,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<CollapseGroup
|
<CollapseGroup
|
||||||
@ -70,6 +71,7 @@ export class CollapseGroupRender extends React.Component<
|
|||||||
expandIconPosition={expandIconPosition}
|
expandIconPosition={expandIconPosition}
|
||||||
className={className}
|
className={className}
|
||||||
style={style}
|
style={style}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
>
|
>
|
||||||
{render('body', body || '')}
|
{render('body', body || '')}
|
||||||
</CollapseGroup>
|
</CollapseGroup>
|
||||||
|
@ -47,6 +47,7 @@ import {
|
|||||||
import {ListenerAction} from 'amis-core';
|
import {ListenerAction} from 'amis-core';
|
||||||
import type {SchemaTokenizeableString} from '../../Schema';
|
import type {SchemaTokenizeableString} from '../../Schema';
|
||||||
import isPlainObject from 'lodash/isPlainObject';
|
import isPlainObject from 'lodash/isPlainObject';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
export type ComboCondition = {
|
export type ComboCondition = {
|
||||||
test: string;
|
test: string;
|
||||||
@ -1285,9 +1286,12 @@ export default class ComboControl extends React.Component<ComboProps> {
|
|||||||
itemRemovableOn,
|
itemRemovableOn,
|
||||||
disabled,
|
disabled,
|
||||||
removable,
|
removable,
|
||||||
deleteBtn
|
deleteBtn,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
const finnalRemovable =
|
const finnalRemovable =
|
||||||
store.removable !== false && // minLength ?
|
store.removable !== false && // minLength ?
|
||||||
!disabled && // 控件自身是否禁用
|
!disabled && // 控件自身是否禁用
|
||||||
@ -1355,7 +1359,7 @@ export default class ComboControl extends React.Component<ComboProps> {
|
|||||||
onClick={this.deleteItem.bind(this, index)}
|
onClick={this.deleteItem.bind(this, index)}
|
||||||
key="delete"
|
key="delete"
|
||||||
className={cx(`Combo-delBtn ${!store.removable ? 'is-disabled' : ''}`)}
|
className={cx(`Combo-delBtn ${!store.removable ? 'is-disabled' : ''}`)}
|
||||||
data-tooltip={__('delete')}
|
data-tooltip={!mobileUI ? __('delete') : null}
|
||||||
data-position="bottom"
|
data-position="bottom"
|
||||||
>
|
>
|
||||||
{deleteIcon ? (
|
{deleteIcon ? (
|
||||||
@ -1460,11 +1464,13 @@ export default class ComboControl extends React.Component<ComboProps> {
|
|||||||
translate: __,
|
translate: __,
|
||||||
itemClassName,
|
itemClassName,
|
||||||
itemsWrapperClassName,
|
itemsWrapperClassName,
|
||||||
static: isStatic
|
static: isStatic,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let items = this.props.items;
|
let items = this.props.items;
|
||||||
let value = this.props.value;
|
let value = this.props.value;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
if (flat && typeof value === 'string') {
|
if (flat && typeof value === 'string') {
|
||||||
value = value.split(delimiter || ',');
|
value = value.split(delimiter || ',');
|
||||||
@ -1474,6 +1480,9 @@ export default class ComboControl extends React.Component<ComboProps> {
|
|||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
`Combo Combo--multi`,
|
`Combo Combo--multi`,
|
||||||
|
{
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
},
|
||||||
multiLine ? `Combo--ver` : `Combo--hor`,
|
multiLine ? `Combo--ver` : `Combo--hor`,
|
||||||
noBorder ? `Combo--noBorder` : '',
|
noBorder ? `Combo--noBorder` : '',
|
||||||
disabled ? 'is-disabled' : '',
|
disabled ? 'is-disabled' : '',
|
||||||
@ -1589,9 +1598,11 @@ export default class ComboControl extends React.Component<ComboProps> {
|
|||||||
typeSwitchable,
|
typeSwitchable,
|
||||||
nullable,
|
nullable,
|
||||||
translate: __,
|
translate: __,
|
||||||
itemClassName
|
itemClassName,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
let items = this.props.items;
|
let items = this.props.items;
|
||||||
const data = isObject(value) ? this.formatValue(value) : this.defaultValue;
|
const data = isObject(value) ? this.formatValue(value) : this.defaultValue;
|
||||||
let condition: ComboCondition | null = null;
|
let condition: ComboCondition | null = null;
|
||||||
@ -1605,6 +1616,9 @@ export default class ComboControl extends React.Component<ComboProps> {
|
|||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
`Combo Combo--single`,
|
`Combo Combo--single`,
|
||||||
|
{
|
||||||
|
'is-mobile': mobileUI
|
||||||
|
},
|
||||||
multiLine ? `Combo--ver` : `Combo--hor`,
|
multiLine ? `Combo--ver` : `Combo--hor`,
|
||||||
noBorder ? `Combo--noBorder` : '',
|
noBorder ? `Combo--noBorder` : '',
|
||||||
disabled ? 'is-disabled' : ''
|
disabled ? 'is-disabled' : ''
|
||||||
|
@ -197,7 +197,8 @@ export class InputFormulaRenderer extends React.Component<InputFormulaProps> {
|
|||||||
data,
|
data,
|
||||||
onPickerOpen,
|
onPickerOpen,
|
||||||
selfVariableName,
|
selfVariableName,
|
||||||
env
|
env,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
let {variables, functions} = this.props;
|
let {variables, functions} = this.props;
|
||||||
|
|
||||||
@ -240,6 +241,7 @@ export class InputFormulaRenderer extends React.Component<InputFormulaProps> {
|
|||||||
onPickerOpen={onPickerOpen}
|
onPickerOpen={onPickerOpen}
|
||||||
selfVariableName={selfVariableName}
|
selfVariableName={selfVariableName}
|
||||||
mixedMode={mixedMode}
|
mixedMode={mixedMode}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
anyChanged
|
anyChanged
|
||||||
} from 'amis-core';
|
} from 'amis-core';
|
||||||
import {FormBaseControlSchema, SchemaCollection} from '../../Schema';
|
import {FormBaseControlSchema, SchemaCollection} from '../../Schema';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InputGroup
|
* InputGroup
|
||||||
@ -190,7 +191,8 @@ export class InputGroup extends React.Component<
|
|||||||
data,
|
data,
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
static: isStatic,
|
static: isStatic,
|
||||||
disabled
|
disabled,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {errorMode} = this.getValidationConfig();
|
const {errorMode} = this.getValidationConfig();
|
||||||
|
|
||||||
@ -218,6 +220,8 @@ export class InputGroup extends React.Component<
|
|||||||
(formHorizontal
|
(formHorizontal
|
||||||
? makeHorizontalDeeper(formHorizontal as any, inputs.length)
|
? makeHorizontalDeeper(formHorizontal as any, inputs.length)
|
||||||
: undefined);
|
: undefined);
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
@ -226,6 +230,9 @@ export class InputGroup extends React.Component<
|
|||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
'is-focused': this.state.isFocused
|
'is-focused': this.state.isFocused
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'is-mobile': mobileUI
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@ -11,7 +11,8 @@ import {
|
|||||||
autobind,
|
autobind,
|
||||||
stripNumber,
|
stripNumber,
|
||||||
filter,
|
filter,
|
||||||
ActionObject
|
ActionObject,
|
||||||
|
isMobile
|
||||||
} from 'amis-core';
|
} from 'amis-core';
|
||||||
import {Range as InputRange, NumberInput, Icon} from 'amis-ui';
|
import {Range as InputRange, NumberInput, Icon} from 'amis-ui';
|
||||||
import {FormBaseControlSchema, SchemaObject} from '../../Schema';
|
import {FormBaseControlSchema, SchemaObject} from '../../Schema';
|
||||||
@ -436,7 +437,8 @@ export class Input extends React.Component<RangeItemProps, any> {
|
|||||||
classPrefix: ns,
|
classPrefix: ns,
|
||||||
disabled,
|
disabled,
|
||||||
max,
|
max,
|
||||||
min
|
min,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const _value = multiple
|
const _value = multiple
|
||||||
? type === 'min'
|
? type === 'min'
|
||||||
@ -454,6 +456,7 @@ export class Input extends React.Component<RangeItemProps, any> {
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onBlur={this.onBlur}
|
onBlur={this.onBlur}
|
||||||
onFocus={this.onFocus}
|
onFocus={this.onFocus}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -638,7 +641,8 @@ export default class RangeControl extends React.PureComponent<
|
|||||||
max,
|
max,
|
||||||
render,
|
render,
|
||||||
marks,
|
marks,
|
||||||
region
|
region,
|
||||||
|
useMobileUI
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
// 处理自定义json配置
|
// 处理自定义json配置
|
||||||
@ -653,6 +657,7 @@ export default class RangeControl extends React.PureComponent<
|
|||||||
(renderMarks[key] = render(region, item as SchemaObject));
|
(renderMarks[key] = render(region, item as SchemaObject));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -660,6 +665,7 @@ export default class RangeControl extends React.PureComponent<
|
|||||||
'RangeControl',
|
'RangeControl',
|
||||||
`${ns}InputRange`,
|
`${ns}InputRange`,
|
||||||
{'is-disabled': disabled},
|
{'is-disabled': disabled},
|
||||||
|
{'is-mobile': mobileUI},
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@ -74,6 +74,7 @@ export default class RepeatControl extends React.Component<RepeatProps, any> {
|
|||||||
placeholder,
|
placeholder,
|
||||||
disabled,
|
disabled,
|
||||||
classPrefix: ns,
|
classPrefix: ns,
|
||||||
|
useMobileUI,
|
||||||
translate: __
|
translate: __
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@ -216,6 +217,7 @@ export default class RepeatControl extends React.Component<RepeatProps, any> {
|
|||||||
searchable={false}
|
searchable={false}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
joinValues={false}
|
joinValues={false}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,6 +8,9 @@ import {Icon} from 'amis-ui';
|
|||||||
import {FormBaseControlSchema, FormSchema, SchemaClassName} from '../../Schema';
|
import {FormBaseControlSchema, FormSchema, SchemaClassName} from '../../Schema';
|
||||||
import Sortable from 'sortablejs';
|
import Sortable from 'sortablejs';
|
||||||
import {findDOMNode} from 'react-dom';
|
import {findDOMNode} from 'react-dom';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
import {PopUp} from 'amis-ui';
|
||||||
|
import {autobind} from 'amis-core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SubForm 子表单
|
* SubForm 子表单
|
||||||
@ -152,6 +155,7 @@ export default class SubFormControl extends React.PureComponent<
|
|||||||
dragTip?: HTMLElement;
|
dragTip?: HTMLElement;
|
||||||
sortable?: Sortable;
|
sortable?: Sortable;
|
||||||
id: string = guid();
|
id: string = guid();
|
||||||
|
tempValue: any;
|
||||||
constructor(props: SubFormProps) {
|
constructor(props: SubFormProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -211,6 +215,7 @@ export default class SubFormControl extends React.PureComponent<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.tempValue = value[index];
|
||||||
this.setState({
|
this.setState({
|
||||||
dialogData: createObject(this.props.data, value[index]),
|
dialogData: createObject(this.props.data, value[index]),
|
||||||
dialogCtx: {
|
dialogCtx: {
|
||||||
@ -255,6 +260,36 @@ export default class SubFormControl extends React.PureComponent<
|
|||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
handlePopupConfirm() {
|
||||||
|
const values = this.tempValue;
|
||||||
|
const {multiple, onChange, value} = this.props;
|
||||||
|
const ctx = this.state.dialogCtx;
|
||||||
|
|
||||||
|
if (multiple) {
|
||||||
|
let newValue = Array.isArray(value) ? value.concat() : [];
|
||||||
|
|
||||||
|
if (ctx?.mode === 'add') {
|
||||||
|
newValue.push({
|
||||||
|
...values
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
newValue[ctx!.index!] = {
|
||||||
|
...newValue[ctx!.index!],
|
||||||
|
...values
|
||||||
|
};
|
||||||
|
}
|
||||||
|
onChange(newValue);
|
||||||
|
} else {
|
||||||
|
onChange({
|
||||||
|
...value,
|
||||||
|
...values
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
dragTipRef(ref: any) {
|
dragTipRef(ref: any) {
|
||||||
if (!this.dragTip && ref) {
|
if (!this.dragTip && ref) {
|
||||||
this.initDragging();
|
this.initDragging();
|
||||||
@ -332,6 +367,28 @@ export default class SubFormControl extends React.PureComponent<
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildFormSchema() {
|
||||||
|
let {form} = this.props;
|
||||||
|
|
||||||
|
const dialogProps = [
|
||||||
|
'title',
|
||||||
|
'actions',
|
||||||
|
'name',
|
||||||
|
'size',
|
||||||
|
'closeOnEsc',
|
||||||
|
'closeOnOutside',
|
||||||
|
'showErrorMsg',
|
||||||
|
'showCloseButton',
|
||||||
|
'bodyClassName',
|
||||||
|
'type'
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'form',
|
||||||
|
...omit(form, dialogProps)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
renderMultipe() {
|
renderMultipe() {
|
||||||
const {
|
const {
|
||||||
addButtonClassName,
|
addButtonClassName,
|
||||||
@ -502,20 +559,48 @@ export default class SubFormControl extends React.PureComponent<
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {multiple, classPrefix: ns, className, style, render} = this.props;
|
const {
|
||||||
|
multiple,
|
||||||
|
classPrefix: ns,
|
||||||
|
className,
|
||||||
|
style,
|
||||||
|
render,
|
||||||
|
useMobileUI
|
||||||
|
} = this.props;
|
||||||
const dialogData = this.state.dialogData;
|
const dialogData = this.state.dialogData;
|
||||||
const dialogCtx = this.state.dialogCtx;
|
const dialogCtx = this.state.dialogCtx;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx(`${ns}SubFormControl`, className)}>
|
<div className={cx(`${ns}SubFormControl`, className)}>
|
||||||
{multiple ? this.renderMultipe() : this.renderSingle()}
|
{multiple ? this.renderMultipe() : this.renderSingle()}
|
||||||
{render(`modal`, this.buildDialogSchema(), {
|
{!mobileUI ? (
|
||||||
show: !!dialogCtx,
|
render(`modal`, this.buildDialogSchema(), {
|
||||||
onClose: this.close,
|
show: !!dialogCtx,
|
||||||
onConfirm: this.handleDialogConfirm,
|
onClose: this.close,
|
||||||
data: dialogData,
|
onConfirm: this.handleDialogConfirm,
|
||||||
formStore: undefined
|
data: dialogData,
|
||||||
})}
|
formStore: undefined
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<PopUp
|
||||||
|
isShow={!!dialogCtx}
|
||||||
|
showConfirm
|
||||||
|
onConfirm={this.handlePopupConfirm}
|
||||||
|
onHide={this.close}
|
||||||
|
>
|
||||||
|
<div className="flex-1 pl-10 pr-10">
|
||||||
|
{render('form', this.buildFormSchema(), {
|
||||||
|
data: dialogData,
|
||||||
|
formStore: undefined,
|
||||||
|
wrapWithPanel: false,
|
||||||
|
onChange: (val: any) => {
|
||||||
|
this.tempValue = val;
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</PopUp>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,14 @@ import find from 'lodash/find';
|
|||||||
import isInteger from 'lodash/isInteger';
|
import isInteger from 'lodash/isInteger';
|
||||||
import unionWith from 'lodash/unionWith';
|
import unionWith from 'lodash/unionWith';
|
||||||
import {findDOMNode} from 'react-dom';
|
import {findDOMNode} from 'react-dom';
|
||||||
import {ResultBox, SpinnerExtraProps} from 'amis-ui';
|
import {PopUp, ResultBox, SpinnerExtraProps} from 'amis-ui';
|
||||||
import {autobind, filterTree, createObject} from 'amis-core';
|
import {autobind, filterTree, createObject} from 'amis-core';
|
||||||
import {Spinner} from 'amis-ui';
|
import {Spinner} from 'amis-ui';
|
||||||
import {Overlay} from 'amis-core';
|
import {Overlay} from 'amis-core';
|
||||||
import {PopOver} from 'amis-core';
|
import {PopOver} from 'amis-core';
|
||||||
import {ListMenu} from 'amis-ui';
|
import {ListMenu, Button} from 'amis-ui';
|
||||||
import {ActionObject} from 'amis-core';
|
import {ActionObject} from 'amis-core';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
import {FormOptionsSchema} from '../../Schema';
|
import {FormOptionsSchema} from '../../Schema';
|
||||||
import {supportStatic} from './StaticHoc';
|
import {supportStatic} from './StaticHoc';
|
||||||
import {TooltipWrapperSchema} from '../TooltipWrapper';
|
import {TooltipWrapperSchema} from '../TooltipWrapper';
|
||||||
@ -98,6 +99,8 @@ export interface TagState {
|
|||||||
inputValue: string;
|
inputValue: string;
|
||||||
isFocused?: boolean;
|
isFocused?: boolean;
|
||||||
isOpened?: boolean;
|
isOpened?: boolean;
|
||||||
|
selectedOptions: Option[];
|
||||||
|
cacheOptions: Option[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TagControl extends React.PureComponent<
|
export default class TagControl extends React.PureComponent<
|
||||||
@ -116,11 +119,16 @@ export default class TagControl extends React.PureComponent<
|
|||||||
separator: '-'
|
separator: '-'
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
constructor(props: TagProps) {
|
||||||
isOpened: false,
|
super(props);
|
||||||
inputValue: '',
|
this.state = {
|
||||||
isFocused: false
|
isOpened: false,
|
||||||
};
|
inputValue: '',
|
||||||
|
isFocused: false,
|
||||||
|
selectedOptions: props.selectedOptions,
|
||||||
|
cacheOptions: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps: TagProps) {
|
componentDidUpdate(prevProps: TagProps) {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
@ -242,9 +250,15 @@ export default class TagControl extends React.PureComponent<
|
|||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
getValue(type: 'push' | 'pop' | 'normal' = 'normal', option: any = {}) {
|
getValue(
|
||||||
const {selectedOptions, joinValues, extractValue, delimiter, valueField} =
|
type: 'push' | 'pop' | 'normal' = 'normal',
|
||||||
this.props;
|
option: any = {},
|
||||||
|
selectedOptions?: Option[]
|
||||||
|
) {
|
||||||
|
const {joinValues, extractValue, delimiter, valueField} = this.props;
|
||||||
|
selectedOptions = selectedOptions
|
||||||
|
? selectedOptions
|
||||||
|
: this.props.selectedOptions;
|
||||||
|
|
||||||
const newValue = selectedOptions.concat();
|
const newValue = selectedOptions.concat();
|
||||||
if (type === 'push') {
|
if (type === 'push') {
|
||||||
@ -286,11 +300,84 @@ export default class TagControl extends React.PureComponent<
|
|||||||
isPrevented || onChange(newValueRes);
|
isPrevented || onChange(newValueRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 移动端特殊处理
|
||||||
|
addItem2(option: Option) {
|
||||||
|
const {useMobileUI, valueField = 'value'} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
if (mobileUI) {
|
||||||
|
const selectedOptions = this.state.selectedOptions.concat();
|
||||||
|
let index = selectedOptions.findIndex(
|
||||||
|
item => item[valueField] === option[valueField]
|
||||||
|
);
|
||||||
|
if (~index) {
|
||||||
|
selectedOptions.splice(index, 1);
|
||||||
|
} else if (!this.isReachMaxFromState()) {
|
||||||
|
selectedOptions.push(option);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
selectedOptions
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手机端校验
|
||||||
|
isExist(inputValue: string) {
|
||||||
|
const {options, valueField = 'value'} = this.props;
|
||||||
|
const {cacheOptions} = this.state;
|
||||||
|
return (
|
||||||
|
options.some(item => item[valueField] === inputValue) ||
|
||||||
|
cacheOptions.some(item => item[valueField] === inputValue)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
addSelection() {
|
||||||
|
let {inputValue} = this.state;
|
||||||
|
const {maxTagLength} = this.props;
|
||||||
|
const selectedOptions = this.state.selectedOptions.slice();
|
||||||
|
const cacheOptions = this.state.cacheOptions.slice();
|
||||||
|
|
||||||
|
if (maxTagLength !== undefined) {
|
||||||
|
inputValue = inputValue.trim();
|
||||||
|
inputValue = inputValue.slice(0, maxTagLength);
|
||||||
|
}
|
||||||
|
if (this.isExist(inputValue)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputValue && !this.isReachMaxFromState()) {
|
||||||
|
const addedValues = this.normalizeInputValue(inputValue);
|
||||||
|
selectedOptions.push(addedValues[0]);
|
||||||
|
cacheOptions.push(addedValues[0]);
|
||||||
|
this.setState({
|
||||||
|
inputValue: '',
|
||||||
|
selectedOptions,
|
||||||
|
cacheOptions
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
async onConfirm() {
|
||||||
|
const {selectedOptions} = this.state;
|
||||||
|
const {onChange} = this.props;
|
||||||
|
const newValueRes = this.getValue('normal', {}, selectedOptions);
|
||||||
|
|
||||||
|
const isPrevented = await this.dispatchEvent('change', {
|
||||||
|
value: newValueRes,
|
||||||
|
selectedItems: selectedOptions
|
||||||
|
});
|
||||||
|
|
||||||
|
isPrevented || onChange(newValueRes);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
async handleFocus(e: any) {
|
async handleFocus(e: any) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isFocused: true,
|
isFocused: true,
|
||||||
isOpened: true
|
isOpened: true,
|
||||||
|
selectedOptions: this.props.selectedOptions
|
||||||
});
|
});
|
||||||
|
|
||||||
const newValueRes = this.getValue('normal');
|
const newValueRes = this.getValue('normal');
|
||||||
@ -303,8 +390,11 @@ export default class TagControl extends React.PureComponent<
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
async handleBlur(e: any) {
|
async handleBlur(e: any) {
|
||||||
const {selectedOptions, onChange} = this.props;
|
const {selectedOptions, onChange, useMobileUI, options} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
if (mobileUI && options.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const value = this.state.inputValue.trim();
|
const value = this.state.inputValue.trim();
|
||||||
|
|
||||||
if (!this.validateInputValue(value)) {
|
if (!this.validateInputValue(value)) {
|
||||||
@ -420,6 +510,12 @@ export default class TagControl extends React.PureComponent<
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleOptionChange(option: Option) {
|
handleOptionChange(option: Option) {
|
||||||
|
const {useMobileUI} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
if (mobileUI) {
|
||||||
|
this.addItem2(option);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.isReachMax() || this.state.inputValue || !option) {
|
if (this.isReachMax() || this.state.inputValue || !option) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -448,6 +544,13 @@ export default class TagControl extends React.PureComponent<
|
|||||||
return max != null && isInteger(max) && selectedOptions.length >= max;
|
return max != null && isInteger(max) && selectedOptions.length >= max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
isReachMaxFromState() {
|
||||||
|
const {selectedOptions} = this.state;
|
||||||
|
const {max} = this.props;
|
||||||
|
return max != null && isInteger(max) && selectedOptions.length >= max;
|
||||||
|
}
|
||||||
|
|
||||||
@supportStatic()
|
@supportStatic()
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
@ -468,16 +571,17 @@ export default class TagControl extends React.PureComponent<
|
|||||||
overflowTagPopover,
|
overflowTagPopover,
|
||||||
translate: __,
|
translate: __,
|
||||||
loadingConfig,
|
loadingConfig,
|
||||||
valueField
|
valueField,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
const finnalOptions = Array.isArray(options)
|
const finnalOptions = Array.isArray(options)
|
||||||
? filterTree(
|
? filterTree(
|
||||||
options,
|
options,
|
||||||
item =>
|
item =>
|
||||||
(Array.isArray(item.children) && !!item.children.length) ||
|
(Array.isArray(item.children) && !!item.children.length) ||
|
||||||
(item[valueField || 'value'] !== undefined &&
|
(item[valueField || 'value'] !== undefined &&
|
||||||
!~selectedOptions.indexOf(item)),
|
(mobileUI || !~selectedOptions.indexOf(item))),
|
||||||
0,
|
0,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@ -488,7 +592,7 @@ export default class TagControl extends React.PureComponent<
|
|||||||
return (
|
return (
|
||||||
<Downshift
|
<Downshift
|
||||||
selectedItem={selectedOptions}
|
selectedItem={selectedOptions}
|
||||||
isOpen={this.state.isFocused}
|
isOpen={mobileUI ? this.state.isOpened : this.state.isFocused}
|
||||||
inputValue={this.state.inputValue}
|
inputValue={this.state.inputValue}
|
||||||
onChange={this.handleOptionChange}
|
onChange={this.handleOptionChange}
|
||||||
itemToString={this.renderItem}
|
itemToString={this.renderItem}
|
||||||
@ -517,7 +621,8 @@ export default class TagControl extends React.PureComponent<
|
|||||||
clearable={clearable}
|
clearable={clearable}
|
||||||
maxTagCount={maxTagCount}
|
maxTagCount={maxTagCount}
|
||||||
overflowTagPopover={overflowTagPopover}
|
overflowTagPopover={overflowTagPopover}
|
||||||
allowInput
|
allowInput={!mobileUI || (mobileUI && !options?.length)}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Spinner loadingConfig={loadingConfig} size="sm" />
|
<Spinner loadingConfig={loadingConfig} size="sm" />
|
||||||
@ -525,40 +630,96 @@ export default class TagControl extends React.PureComponent<
|
|||||||
</ResultBox>
|
</ResultBox>
|
||||||
|
|
||||||
{dropdown !== false ? (
|
{dropdown !== false ? (
|
||||||
<Overlay
|
mobileUI ? (
|
||||||
container={popOverContainer || this.getParent}
|
<PopUp
|
||||||
target={this.getTarget}
|
className={cx(`Tag-popup`)}
|
||||||
placement={'auto'}
|
container={popOverContainer}
|
||||||
show={isOpen && !!finnalOptions.length}
|
isShow={isOpen && !!finnalOptions.length}
|
||||||
>
|
showConfirm={true}
|
||||||
<PopOver
|
onConfirm={this.onConfirm}
|
||||||
overlay
|
|
||||||
className={cx('TagControl-popover')}
|
|
||||||
onHide={this.close}
|
onHide={this.close}
|
||||||
>
|
>
|
||||||
<ListMenu
|
<div>
|
||||||
options={finnalOptions}
|
<ListMenu
|
||||||
itemRender={this.renderItem}
|
selectedOptions={selectedOptions}
|
||||||
highlightIndex={highlightedIndex}
|
useMobileUI={useMobileUI}
|
||||||
getItemProps={({
|
options={finnalOptions.concat(this.state.cacheOptions)}
|
||||||
item,
|
itemRender={this.renderItem}
|
||||||
index
|
highlightIndex={highlightedIndex}
|
||||||
}: {
|
getItemProps={({
|
||||||
item: Option;
|
|
||||||
index: number;
|
|
||||||
}) => ({
|
|
||||||
...getItemProps({
|
|
||||||
index,
|
|
||||||
item,
|
item,
|
||||||
disabled: reachMax || item.disabled,
|
index
|
||||||
className: cx('ListMenu-item', {
|
}: {
|
||||||
'is-disabled': reachMax
|
item: Option;
|
||||||
|
index: number;
|
||||||
|
}) => ({
|
||||||
|
...getItemProps({
|
||||||
|
index,
|
||||||
|
item,
|
||||||
|
className: cx('ListMenu-item', {
|
||||||
|
'is-active': ~(
|
||||||
|
this.state.selectedOptions.map(
|
||||||
|
item => item[valueField]
|
||||||
|
) || []
|
||||||
|
).indexOf(item[valueField])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})}
|
||||||
})}
|
/>
|
||||||
/>
|
{mobileUI && !this.isReachMaxFromState() ? (
|
||||||
</PopOver>
|
<div className={cx('ListMenu-add-wrap')}>
|
||||||
</Overlay>
|
<ResultBox
|
||||||
|
placeholder={__('SubForm.add')}
|
||||||
|
allowInput
|
||||||
|
value={this.state.inputValue}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
|
clearable
|
||||||
|
maxTagCount={maxTagCount}
|
||||||
|
onChange={value => {
|
||||||
|
this.setState({inputValue: value});
|
||||||
|
}}
|
||||||
|
onBlur={this.addSelection}
|
||||||
|
></ResultBox>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</PopUp>
|
||||||
|
) : (
|
||||||
|
<Overlay
|
||||||
|
container={popOverContainer || this.getParent}
|
||||||
|
target={this.getTarget}
|
||||||
|
placement={'auto'}
|
||||||
|
show={isOpen && !!finnalOptions.length}
|
||||||
|
>
|
||||||
|
<PopOver
|
||||||
|
overlay
|
||||||
|
className={cx('TagControl-popover')}
|
||||||
|
onHide={this.close}
|
||||||
|
>
|
||||||
|
<ListMenu
|
||||||
|
options={finnalOptions}
|
||||||
|
itemRender={this.renderItem}
|
||||||
|
highlightIndex={highlightedIndex}
|
||||||
|
getItemProps={({
|
||||||
|
item,
|
||||||
|
index
|
||||||
|
}: {
|
||||||
|
item: Option;
|
||||||
|
index: number;
|
||||||
|
}) => ({
|
||||||
|
...getItemProps({
|
||||||
|
index,
|
||||||
|
item,
|
||||||
|
disabled: reachMax || item.disabled,
|
||||||
|
className: cx('ListMenu-item', {
|
||||||
|
'is-disabled': reachMax
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</PopOver>
|
||||||
|
</Overlay>
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
// 保留原来的展现方式,不推荐
|
// 保留原来的展现方式,不推荐
|
||||||
<div className={cx('TagControl-sug')}>
|
<div className={cx('TagControl-sug')}>
|
||||||
|
@ -173,6 +173,7 @@ export interface TreeProps
|
|||||||
SpinnerExtraProps {
|
SpinnerExtraProps {
|
||||||
enableNodePath?: boolean;
|
enableNodePath?: boolean;
|
||||||
pathSeparator?: string;
|
pathSeparator?: string;
|
||||||
|
useMobileUI?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TreeState {
|
interface TreeState {
|
||||||
@ -377,7 +378,8 @@ export default class TreeControl extends React.Component<TreeProps, TreeState> {
|
|||||||
enableDefaultIcon,
|
enableDefaultIcon,
|
||||||
searchable,
|
searchable,
|
||||||
searchConfig = {},
|
searchConfig = {},
|
||||||
heightAuto
|
heightAuto,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
let {highlightTxt} = this.props;
|
let {highlightTxt} = this.props;
|
||||||
const {filteredOptions, keyword} = this.state;
|
const {filteredOptions, keyword} = this.state;
|
||||||
@ -439,6 +441,7 @@ export default class TreeControl extends React.Component<TreeProps, TreeState> {
|
|||||||
itemHeight={toNumber(itemHeight) > 0 ? toNumber(itemHeight) : undefined}
|
itemHeight={toNumber(itemHeight) > 0 ? toNumber(itemHeight) : undefined}
|
||||||
itemRender={menuTpl ? this.renderOptionItem : undefined}
|
itemRender={menuTpl ? this.renderOptionItem : undefined}
|
||||||
enableDefaultIcon={enableDefaultIcon}
|
enableDefaultIcon={enableDefaultIcon}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -467,6 +470,7 @@ export default class TreeControl extends React.Component<TreeProps, TreeState> {
|
|||||||
clearable={true}
|
clearable={true}
|
||||||
{...omit(searchConfig, 'className', 'sticky')}
|
{...omit(searchConfig, 'className', 'sticky')}
|
||||||
onSearch={this.handleSearch}
|
onSearch={this.handleSearch}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
{TreeCmpt}
|
{TreeCmpt}
|
||||||
</>
|
</>
|
||||||
|
@ -138,11 +138,12 @@ export default class JSONSchemaEditorControl extends React.PureComponent<JSONSch
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {enableAdvancedSetting, env, ...rest} = this.props;
|
const {enableAdvancedSetting, useMobileUI, env, ...rest} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<JSONSchemaEditor
|
<JSONSchemaEditor
|
||||||
{...rest}
|
{...rest}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
placeholder={this.normalizePlaceholder()}
|
placeholder={this.normalizePlaceholder()}
|
||||||
enableAdvancedSetting={enableAdvancedSetting}
|
enableAdvancedSetting={enableAdvancedSetting}
|
||||||
renderModalProps={this.renderModalProps}
|
renderModalProps={this.renderModalProps}
|
||||||
|
@ -956,7 +956,7 @@ export default class NestedSelectControl extends React.Component<
|
|||||||
onKeyDown={this.handleInputKeyDown}
|
onKeyDown={this.handleInputKeyDown}
|
||||||
clearable={clearable}
|
clearable={clearable}
|
||||||
hasDropDownArrow={true}
|
hasDropDownArrow={true}
|
||||||
allowInput={searchable}
|
allowInput={searchable && !mobileUI}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Spinner loadingConfig={loadingConfig} size="sm" />
|
<Spinner loadingConfig={loadingConfig} size="sm" />
|
||||||
|
@ -23,8 +23,10 @@ import {
|
|||||||
resolveEventData
|
resolveEventData
|
||||||
} from 'amis-core';
|
} from 'amis-core';
|
||||||
import {Html, Icon} from 'amis-ui';
|
import {Html, Icon} from 'amis-ui';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
import {FormOptionsSchema, SchemaTpl} from '../../Schema';
|
import {FormOptionsSchema, SchemaTpl} from '../../Schema';
|
||||||
import intersectionWith from 'lodash/intersectionWith';
|
import intersectionWith from 'lodash/intersectionWith';
|
||||||
|
import {PopUp} from 'amis-ui';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Picker
|
* Picker
|
||||||
@ -521,11 +523,14 @@ export default class PickerControl extends React.PureComponent<
|
|||||||
translate: __,
|
translate: __,
|
||||||
popOverContainer,
|
popOverContainer,
|
||||||
modalTitle,
|
modalTitle,
|
||||||
data
|
data,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx(`PickerControl`, className)}>
|
<div className={cx(`PickerControl`, {'is-mobile': mobileUI}, className)}>
|
||||||
{embed ? (
|
{embed ? (
|
||||||
<div className={cx('Picker')}>
|
<div className={cx('Picker')}>
|
||||||
{this.renderBody({popOverContainer})}
|
{this.renderBody({popOverContainer})}
|
||||||
@ -556,6 +561,7 @@ export default class PickerControl extends React.PureComponent<
|
|||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
|
readOnly={mobileUI}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -301,7 +301,8 @@ export class TabsTransferRenderer extends BaseTabsTransferRenderer<TabsTransferP
|
|||||||
loadingConfig,
|
loadingConfig,
|
||||||
valueField = 'value',
|
valueField = 'value',
|
||||||
labelField = 'label',
|
labelField = 'label',
|
||||||
data
|
data,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -332,6 +333,7 @@ export class TabsTransferRenderer extends BaseTabsTransferRenderer<TabsTransferP
|
|||||||
labelField={labelField}
|
labelField={labelField}
|
||||||
valueField={valueField}
|
valueField={valueField}
|
||||||
ctx={data}
|
ctx={data}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
|
@ -106,7 +106,8 @@ export class TabsTransferPickerRenderer extends BaseTabsTransferRenderer<TabsTra
|
|||||||
virtualThreshold,
|
virtualThreshold,
|
||||||
loadingConfig,
|
loadingConfig,
|
||||||
labelField = 'label',
|
labelField = 'label',
|
||||||
valueField = 'value'
|
valueField = 'value',
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -139,6 +140,7 @@ export class TabsTransferPickerRenderer extends BaseTabsTransferRenderer<TabsTra
|
|||||||
virtualThreshold={virtualThreshold}
|
virtualThreshold={virtualThreshold}
|
||||||
labelField={labelField}
|
labelField={labelField}
|
||||||
valueField={valueField}
|
valueField={valueField}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
|
@ -532,7 +532,8 @@ export class BaseTransferRenderer<
|
|||||||
itemHeight,
|
itemHeight,
|
||||||
loadingConfig,
|
loadingConfig,
|
||||||
showInvalidMatch,
|
showInvalidMatch,
|
||||||
onlyChildren
|
onlyChildren,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// 目前 LeftOptions 没有接口可以动态加载
|
// 目前 LeftOptions 没有接口可以动态加载
|
||||||
@ -593,6 +594,7 @@ export class BaseTransferRenderer<
|
|||||||
}
|
}
|
||||||
loadingConfig={loadingConfig}
|
loadingConfig={loadingConfig}
|
||||||
showInvalidMatch={showInvalidMatch}
|
showInvalidMatch={showInvalidMatch}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
|
@ -85,7 +85,8 @@ export class TransferPickerRenderer extends BaseTransferRenderer<TabsTransferPro
|
|||||||
virtualThreshold,
|
virtualThreshold,
|
||||||
loadingConfig,
|
loadingConfig,
|
||||||
labelField = 'label',
|
labelField = 'label',
|
||||||
valueField = 'value'
|
valueField = 'value',
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// 目前 LeftOptions 没有接口可以动态加载
|
// 目前 LeftOptions 没有接口可以动态加载
|
||||||
@ -135,6 +136,7 @@ export class TransferPickerRenderer extends BaseTransferRenderer<TabsTransferPro
|
|||||||
toNumber(itemHeight) > 0 ? toNumber(itemHeight) : undefined
|
toNumber(itemHeight) > 0 ? toNumber(itemHeight) : undefined
|
||||||
}
|
}
|
||||||
virtualThreshold={virtualThreshold}
|
virtualThreshold={virtualThreshold}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
|
@ -135,6 +135,7 @@ export interface TreeSelectProps
|
|||||||
export interface TreeSelectState {
|
export interface TreeSelectState {
|
||||||
isOpened: boolean;
|
isOpened: boolean;
|
||||||
inputValue: string;
|
inputValue: string;
|
||||||
|
tempValue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TreeSelectControl extends React.Component<
|
export default class TreeSelectControl extends React.Component<
|
||||||
@ -182,12 +183,15 @@ export default class TreeSelectControl extends React.Component<
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
inputValue: '',
|
inputValue: '',
|
||||||
|
tempValue: '',
|
||||||
isOpened: false
|
isOpened: false
|
||||||
};
|
};
|
||||||
|
|
||||||
this.open = this.open.bind(this);
|
this.open = this.open.bind(this);
|
||||||
this.close = this.close.bind(this);
|
this.close = this.close.bind(this);
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
|
this.handleTempChange = this.handleTempChange.bind(this);
|
||||||
|
this.handleConfirm = this.handleConfirm.bind(this);
|
||||||
this.clearValue = this.clearValue.bind(this);
|
this.clearValue = this.clearValue.bind(this);
|
||||||
this.handleFocus = this.handleFocus.bind(this);
|
this.handleFocus = this.handleFocus.bind(this);
|
||||||
this.handleBlur = this.handleBlur.bind(this);
|
this.handleBlur = this.handleBlur.bind(this);
|
||||||
@ -316,6 +320,22 @@ export default class TreeSelectControl extends React.Component<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleTempChange(value: any) {
|
||||||
|
this.setState({
|
||||||
|
tempValue: value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleConfirm() {
|
||||||
|
this.close();
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
inputValue: ''
|
||||||
|
},
|
||||||
|
() => this.resultChangeEvent(this.state.tempValue)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
handleInputChange(value: string) {
|
handleInputChange(value: string) {
|
||||||
const {autoComplete, data} = this.props;
|
const {autoComplete, data} = this.props;
|
||||||
|
|
||||||
@ -582,13 +602,15 @@ export default class TreeSelectControl extends React.Component<
|
|||||||
virtualThreshold,
|
virtualThreshold,
|
||||||
itemHeight,
|
itemHeight,
|
||||||
menuTpl,
|
menuTpl,
|
||||||
enableDefaultIcon
|
enableDefaultIcon,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let filtedOptions =
|
let filtedOptions =
|
||||||
!isEffectiveApi(autoComplete) && searchable && this.state.inputValue
|
!isEffectiveApi(autoComplete) && searchable && this.state.inputValue
|
||||||
? this.filterOptions(options, this.state.inputValue)
|
? this.filterOptions(options, this.state.inputValue)
|
||||||
: options;
|
: options;
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TreeSelector
|
<TreeSelector
|
||||||
@ -599,7 +621,7 @@ export default class TreeSelectControl extends React.Component<
|
|||||||
labelField={labelField}
|
labelField={labelField}
|
||||||
valueField={valueField}
|
valueField={valueField}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={this.handleChange}
|
onChange={mobileUI ? this.handleTempChange : this.handleChange}
|
||||||
joinValues={joinValues}
|
joinValues={joinValues}
|
||||||
extractValue={extractValue}
|
extractValue={extractValue}
|
||||||
delimiter={delimiter}
|
delimiter={delimiter}
|
||||||
@ -644,6 +666,7 @@ export default class TreeSelectControl extends React.Component<
|
|||||||
itemHeight={toNumber(itemHeight) > 0 ? toNumber(itemHeight) : undefined}
|
itemHeight={toNumber(itemHeight) > 0 ? toNumber(itemHeight) : undefined}
|
||||||
itemRender={menuTpl ? this.renderOptionItem : undefined}
|
itemRender={menuTpl ? this.renderOptionItem : undefined}
|
||||||
enableDefaultIcon={enableDefaultIcon}
|
enableDefaultIcon={enableDefaultIcon}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -711,8 +734,10 @@ export default class TreeSelectControl extends React.Component<
|
|||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
onKeyDown={this.handleInputKeyDown}
|
onKeyDown={this.handleInputKeyDown}
|
||||||
clearable={clearable}
|
clearable={clearable}
|
||||||
allowInput={searchable || isEffectiveApi(autoComplete)}
|
allowInput={!mobileUI && (searchable || isEffectiveApi(autoComplete))}
|
||||||
hasDropDownArrow
|
hasDropDownArrow
|
||||||
|
readOnly={mobileUI}
|
||||||
|
useMobileUI
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Spinner loadingConfig={loadingConfig} size="sm" />
|
<Spinner loadingConfig={loadingConfig} size="sm" />
|
||||||
@ -745,6 +770,8 @@ export default class TreeSelectControl extends React.Component<
|
|||||||
className={cx(`${ns}TreeSelect-popup`)}
|
className={cx(`${ns}TreeSelect-popup`)}
|
||||||
isShow={isOpened}
|
isShow={isOpened}
|
||||||
onHide={this.close}
|
onHide={this.close}
|
||||||
|
showConfirm
|
||||||
|
onConfirm={this.handleConfirm}
|
||||||
>
|
>
|
||||||
{this.renderOuter()}
|
{this.renderOuter()}
|
||||||
</PopUp>
|
</PopUp>
|
||||||
|
@ -196,7 +196,8 @@ export class SearchBoxRenderer extends React.Component<
|
|||||||
placeholder,
|
placeholder,
|
||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
style
|
style,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const value = this.state.value;
|
const value = this.state.value;
|
||||||
@ -221,6 +222,7 @@ export class SearchBoxRenderer extends React.Component<
|
|||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
onFocus={() => this.dispatchEvent('focus')}
|
onFocus={() => this.dispatchEvent('focus')}
|
||||||
onBlur={() => this.dispatchEvent('blur')}
|
onBlur={() => this.dispatchEvent('blur')}
|
||||||
|
useMobileUI={useMobileUI}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ import {getStyleNumber} from 'amis-core';
|
|||||||
import {exportExcel} from './exportExcel';
|
import {exportExcel} from './exportExcel';
|
||||||
import type {IColumn, IRow} from 'amis-core';
|
import type {IColumn, IRow} from 'amis-core';
|
||||||
import intersection from 'lodash/intersection';
|
import intersection from 'lodash/intersection';
|
||||||
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 表格列,不指定类型时默认为文本类型。
|
* 表格列,不指定类型时默认为文本类型。
|
||||||
@ -3040,7 +3041,8 @@ export default class Table extends React.Component<TableProps, object> {
|
|||||||
classnames: cx,
|
classnames: cx,
|
||||||
affixColumns,
|
affixColumns,
|
||||||
autoFillHeight,
|
autoFillHeight,
|
||||||
autoGenerateFilter
|
autoGenerateFilter,
|
||||||
|
useMobileUI
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
this.renderedToolbars = []; // 用来记录哪些 toolbar 已经渲染了,已经渲染了就不重复渲染了。
|
this.renderedToolbars = []; // 用来记录哪些 toolbar 已经渲染了,已经渲染了就不重复渲染了。
|
||||||
@ -3050,10 +3052,11 @@ export default class Table extends React.Component<TableProps, object> {
|
|||||||
const tableClassName = cx('Table-table', this.props.tableClassName, {
|
const tableClassName = cx('Table-table', this.props.tableClassName, {
|
||||||
'Table-table--withCombine': store.combineNum > 0
|
'Table-table--withCombine': store.combineNum > 0
|
||||||
});
|
});
|
||||||
|
const mobileUI = useMobileUI && isMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx('Table', className, {
|
className={cx('Table', {'is-mobile': mobileUI}, className, {
|
||||||
'Table--unsaved': !!store.modified || !!store.moved,
|
'Table--unsaved': !!store.modified || !!store.moved,
|
||||||
'Table--autoFillHeight': autoFillHeight
|
'Table--autoFillHeight': autoFillHeight
|
||||||
})}
|
})}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user