Skip to content

Commit d9b4abb

Browse files
authored
feat:select-wrapper多端 (#3881)
1 parent 763f03d commit d9b4abb

File tree

11 files changed

+562
-17
lines changed

11 files changed

+562
-17
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { iconChevronDown } from '@opentiny/vue-icon'
2+
3+
export default {
4+
// 虚拟滚动的默认options不一致
5+
baseOpts: { optionHeight: 34, limit: 20 },
6+
icons: {
7+
dropdownIcon: iconChevronDown()
8+
},
9+
state: {
10+
sizeMap: {
11+
default: 30,
12+
mini: 24,
13+
small: 36,
14+
medium: 42
15+
},
16+
spacingHeight: 2,
17+
initialInputHeight: 30,
18+
// 显示清除等图标时,不隐藏下拉箭头时
19+
autoHideDownIcon: false,
20+
delayBlur: true
21+
},
22+
props: {
23+
tagType: 'info',
24+
stopPropagation: true
25+
},
26+
renderless: (props, hooks, { emit }, api) => {
27+
const state = api.state
28+
29+
return {
30+
// 兼容不同主题输入框尺寸对应标签尺寸不一致
31+
computedCollapseTagSize: () => {
32+
let size = 'small'
33+
34+
if (~['small', 'mini'].indexOf(state.selectSize)) {
35+
size = state.selectSize
36+
} else if (~['medium', 'default'].indexOf(state.selectSize)) {
37+
size = 'small'
38+
}
39+
40+
return size
41+
},
42+
// 兼容显示清除图标时,是否同时显示下拉图标
43+
computedShowDropdownIcon: () => {
44+
return !(props.remote && props.filterable && !props.remoteConfig.showIcon)
45+
},
46+
47+
// aui 的勾选未处理disabled的选项,故此放这里。
48+
toggleCheckAll: (filtered) => {
49+
const getEnabledValues = (options) => {
50+
let values = []
51+
52+
for (let i = 0; i < options.length; i++) {
53+
if (!options[i].state.disabled && !options[i].state.groupDisabled && options[i].state.visible) {
54+
values.push(options[i].value)
55+
}
56+
}
57+
58+
return values
59+
}
60+
61+
let value
62+
const enabledValues = getEnabledValues(state.options)
63+
64+
if (filtered) {
65+
if (state.filteredSelectCls === 'check' || state.filteredSelectCls === 'halfselect') {
66+
value = Array.from(new Set([...state.modelValue, ...enabledValues]))
67+
} else {
68+
value = state.modelValue.filter((val) => !enabledValues.includes(val))
69+
}
70+
} else {
71+
if (state.selectCls === 'check') {
72+
value = enabledValues
73+
} else if (state.selectCls === 'halfselect') {
74+
const unchecked = state.options.filter((item) => !item.state.disabled && item.state.selectCls === 'check')
75+
76+
unchecked.length ? (value = enabledValues) : (value = [])
77+
} else if (state.selectCls === 'checked-sur') {
78+
value = []
79+
}
80+
}
81+
82+
const requiredValue = []
83+
if (props.multiple) {
84+
state.options.forEach((opt) => {
85+
if (opt.required) requiredValue.push(opt.value)
86+
})
87+
}
88+
89+
if (Array.isArray(value)) {
90+
value = requiredValue.concat(value.filter((val) => !requiredValue.find((requireVal) => requireVal === val)))
91+
}
92+
93+
api.setSoftFocus()
94+
95+
state.isSilentBlur = true
96+
api.updateModelValue(value)
97+
api.directEmitChange(value)
98+
},
99+
// aurora 禁用和只展示的时候都是tagText,默认主题是 isDisplayOnly 才显示tagText
100+
computedShowTagText: () => {
101+
return state.isDisabled || state.isDisplayOnly
102+
},
103+
// aurora 禁用已选项无效果,必选不显示关闭图标
104+
isTagClosable: (item) => {
105+
return !item.required
106+
}
107+
}
108+
}
109+
}
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { iconChevronDown, iconPlus } from '@opentiny/vue-icon'
2+
import loadingIcon from './icon-loading.svg'
3+
4+
export default {
5+
// 虚拟滚动的默认options不一致
6+
baseOpts: { optionHeight: 34, limit: 20 },
7+
icons: {
8+
dropdownIcon: iconChevronDown(),
9+
addIcon: iconPlus(),
10+
loadingIcon
11+
},
12+
state: {
13+
sizeMap: {
14+
default: 28,
15+
mini: 24,
16+
small: 28,
17+
medium: 32
18+
},
19+
spacingHeight: 4,
20+
initialInputHeight: 28,
21+
// 显示清除等图标时,不隐藏下拉箭头时
22+
autoHideDownIcon: false,
23+
delayBlur: true
24+
},
25+
props: {
26+
tagType: 'info',
27+
stopPropagation: true
28+
},
29+
renderless: (props, hooks, { emit }, api) => {
30+
const state = api.state
31+
32+
return {
33+
computedCollapseTagSize: () => {
34+
let size = 'small'
35+
36+
if (~['small', 'mini'].indexOf(state.selectSize)) {
37+
size = state.selectSize
38+
} else if (~['medium', 'default'].indexOf(state.selectSize)) {
39+
size = 'small'
40+
}
41+
42+
return size
43+
},
44+
// aui 的勾选未处理disabled的选项,故此放这里。
45+
toggleCheckAll: (filtered) => {
46+
const getEnabledValues = (options) => {
47+
let values = []
48+
49+
for (let i = 0; i < options.length; i++) {
50+
if (!options[i].state.disabled && !options[i].state.groupDisabled && options[i].state.visible) {
51+
values.push(options[i].value)
52+
}
53+
}
54+
55+
return values
56+
}
57+
58+
let value
59+
const enabledValues = getEnabledValues(state.options)
60+
61+
if (filtered) {
62+
if (state.filteredSelectCls === 'check' || state.filteredSelectCls === 'halfselect') {
63+
value = Array.from(new Set([...state.modelValue, ...enabledValues]))
64+
} else {
65+
value = state.modelValue.filter((val) => !enabledValues.includes(val))
66+
}
67+
} else {
68+
if (state.selectCls === 'check') {
69+
value = enabledValues
70+
} else if (state.selectCls === 'halfselect') {
71+
const unchecked = state.options.filter((item) => !item.state.disabled && item.state.selectCls === 'check')
72+
73+
unchecked.length ? (value = enabledValues) : (value = [])
74+
} else if (state.selectCls === 'checked-sur') {
75+
value = []
76+
}
77+
}
78+
79+
const requiredValue = []
80+
if (props.multiple) {
81+
state.options.forEach((opt) => {
82+
if (opt.required) requiredValue.push(opt.value)
83+
})
84+
}
85+
86+
if (Array.isArray(value)) {
87+
value = requiredValue.concat(value.filter((val) => !requiredValue.find((requireVal) => requireVal === val)))
88+
}
89+
90+
api.setSoftFocus()
91+
92+
state.isSilentBlur = true
93+
api.updateModelValue(value)
94+
api.directEmitChange(value)
95+
},
96+
// aurora 禁用和只展示的时候都是tagText,默认主题是 isDisplayOnly 才显示tagText
97+
computedShowTagText: () => {
98+
return state.isDisabled || state.isDisplayOnly
99+
},
100+
// aurora 禁用已选项无效果,必选不显示关闭图标
101+
isTagClosable: (item) => {
102+
return !item.required
103+
}
104+
}
105+
}
106+
}

packages/renderless/src/base-select/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,9 @@ const postOperOfToVisible = ({ props, state, constants, vm }) => {
12491249
if (props.modelValue && props.initLabel && !state.selectedLabel) {
12501250
state.selectedLabel = props.initLabel
12511251
}
1252+
} else if (props.modelValue && props.initLabel) {
1253+
// 如果 state.selected 不存在,但有 modelValue 和 initLabel,则使用 initLabel
1254+
state.selectedLabel = props.initLabel
12521255
}
12531256
}
12541257

packages/renderless/src/select-wrapper/vue.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ export const renderless = (props, { reactive, computed, useAttrs }, { constants,
2525
: ['tiny-select']
2626

2727
const { class: _omitClass, ...restAttrs } = attrs
28-
2928
return {
3029
...props,
3130
...restAttrs,
32-
class: classArray
31+
class: Array.from(new Set(classArray)),
32+
dataTag: 'tiny-select'
3333
}
3434
})
3535

packages/vue/src/base-select/src/mobile-first.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@
302302
:display-only-content="state.displayOnlyContent"
303303
:unselectable="state.readonly ? 'on' : 'off'"
304304
:validate-event="false"
305+
:show-empty-value="showEmptyValue"
306+
:input-box-type="inputBoxType"
305307
:tabindex="multiple && filterable ? '-1' : tabindex"
306308
@focus="handleFocus"
307309
@blur="handleBlur"
@@ -758,7 +760,10 @@ export default defineComponent({
758760
'showAllTextTag',
759761
'hoverExpand',
760762
'clickExpand',
761-
'maxVisibleRows'
763+
'maxVisibleRows',
764+
'initLabel',
765+
'inputBoxType',
766+
'showEmptyValue'
762767
],
763768
setup(props, context) {
764769
return setup({ props, context, renderless, api, classes })

packages/vue/src/grid-select/src/mobile-first.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
ref="gridRef"
3838
auto-resize
3939
:row-id="valueField"
40-
:select-config="state.selectConfig"
41-
:radio-config="state.radioConfig"
40+
:select-config="buildSelectConfig()"
41+
:radio-config="buildRadioConfig()"
4242
:highlight-current-row="true"
4343
:columns="gridOp?.columns || []"
4444
:data="Array.isArray(state.gridData) ? state.gridData : state.gridData?.data || state.gridData || []"

packages/vue/src/input/src/mobile-first.vue

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,15 @@
9494
? 'h-6 leading-6 text-xs placeholder:text-xs'
9595
: 'h-7 leading-7',
9696
slots.prepend || slots.append ? 'align-middle table-cell' : 'inline-block',
97-
slots.prepend && slots.append
98-
? 'rounded-none'
99-
: slots.prepend
100-
? 'rounded-tl-none rounded-bl-none rounded-tr rounded-br'
101-
: slots.append
102-
? 'rounded-tl rounded-bl rounded-tr-none rounded-br-none'
103-
: 'rounded',
97+
inputBoxType === 'underline'
98+
? 'rounded-none border-t-0 border-l-0 border-r-0 border-b sm:border-b'
99+
: slots.prepend && slots.append
100+
? 'rounded-none'
101+
: slots.prepend
102+
? 'rounded-tl-none rounded-bl-none rounded-tr rounded-br'
103+
: slots.append
104+
? 'rounded-tl rounded-bl rounded-tr-none rounded-br-none'
105+
: 'rounded',
104106
readonly ? ' text-ellipsis overflow-hidden whitespace-nowrap' : 'sm:border',
105107
(slots.prefix || prefixIcon) && (slots.suffix || suffixIcon || clearable || showPassword)
106108
? 'px-6 sm:px-6'
@@ -427,7 +429,8 @@ export default defineComponent({
427429
'popupMore',
428430
'showTooltip',
429431
'frontClearIcon',
430-
'hoverExpand'
432+
'hoverExpand',
433+
'inputBoxType'
431434
],
432435
setup(props, context): any {
433436
return setup({ props, context, renderless, api })

packages/vue/src/select-wrapper/src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import { $props, $prefix, $setup, defineComponent } from '@opentiny/vue-common'
1414
import { t } from '@opentiny/vue-locale'
15-
import template from 'virtual-template?pc'
15+
import template from 'virtual-template?pc|mobile-first'
1616

1717
const $constants = {
1818
CLASS: {
@@ -326,9 +326,9 @@ export default defineComponent({
326326
type: Boolean,
327327
default: false
328328
},
329-
InputBoxType: {
329+
inputBoxType: {
330330
type: String,
331-
default: 'input',
331+
default: 'normal',
332332
validator: (value: string) => ['input', 'underline'].includes(value)
333333
},
334334
tagType: {

0 commit comments

Comments
 (0)