diff --git a/packages/devui-vue/devui/checkbox/src/checkbox-group.tsx b/packages/devui-vue/devui/checkbox/src/checkbox-group.tsx index 677f2ff5eafe7f9f0e69c77a27f8148527b68fe4..58551aeaf5e0e35301b7e2ba03ea9952c97137da 100644 --- a/packages/devui-vue/devui/checkbox/src/checkbox-group.tsx +++ b/packages/devui-vue/devui/checkbox/src/checkbox-group.tsx @@ -1,35 +1,54 @@ -import { defineComponent, ExtractPropTypes, provide, toRef } from 'vue'; -import { checkboxGroupProps, checkboxGroupInjectionKey } from './use-checkbox'; -import DCheckbox from './checkbox'; -import './checkbox-group.scss'; +import { defineComponent, ExtractPropTypes, provide, toRef } from 'vue' +import { checkboxGroupProps, checkboxGroupInjectionKey } from './use-checkbox' +import DCheckbox from './checkbox' +import './checkbox-group.scss' export default defineComponent({ name: 'DCheckboxGroup', props: checkboxGroupProps, emits: ['change', 'update:modelValue'], setup(props: ExtractPropTypes, ctx) { - const valList = toRef(props, 'modelValue'); + const valList = toRef(props, 'modelValue') + const defaultOpt = { checked: false, isShowTitle: true, halfchecked: false, showAnimation: true, disabled: false, - }; - + } const toggleGroupVal = (val: string) => { - const index = valList.value.findIndex((item) => item === val); + let index = -1 + if (typeof valList.value[0] === 'string') { + index = valList.value.findIndex((item) => item === val) + } else if (typeof valList.value[0] === 'object') { + index = valList.value.findIndex((item) => item.value === val) + } + if (index === -1) { - const res = [...valList.value, val]; - ctx.emit('update:modelValue', res); - ctx.emit('change', res); - return; + if (typeof props.options[0] === 'object') { + const newOne = props.options.find((item) => item.value === val) + const res = [...valList.value, newOne] + ctx.emit('update:modelValue', res) + ctx.emit('change', res) + return + } + const res = [...valList.value, val] + ctx.emit('update:modelValue', res) + ctx.emit('change', res) + return } - valList.value.splice(index, 1); - ctx.emit('update:modelValue', valList.value); - ctx.emit('change', valList.value); - }; - const isItemChecked = (itemVal: string) => valList.value.includes(itemVal); + valList.value.splice(index, 1) + ctx.emit('update:modelValue', valList.value) + ctx.emit('change', valList.value) + } + const isItemChecked = (itemVal: string) => { + if (typeof valList.value[0] === 'string') { + return valList.value.includes(itemVal) + } else if (typeof valList.value[0] === 'object') { + return valList.value.some((item) => item.value === itemVal) + } + } provide(checkboxGroupInjectionKey, { disabled: toRef(props, 'disabled'), @@ -41,21 +60,33 @@ export default defineComponent({ toggleGroupVal, itemWidth: toRef(props, 'itemWidth'), direction: toRef(props, 'direction'), - }); + }) return { defaultOpt, - }; + } }, render() { - const { direction, $slots, defaultOpt, options } = this; - let children = $slots.default?.(); + const { direction, $slots, defaultOpt, options } = this + let children = $slots.default?.() if (options?.length > 0) { children = options.map((opt) => { - const mergedOpt = Object.assign({}, defaultOpt, opt); - return ; - }); + let mergedOpt = null + if (typeof opt === 'string') { + mergedOpt = Object.assign({}, defaultOpt, { + label: opt, + value: opt, + }) + } else if (typeof opt === 'object') { + mergedOpt = Object.assign({}, defaultOpt, { + ...opt, + label: opt.name, + }) + } + + return + }) } return ( @@ -64,6 +95,6 @@ export default defineComponent({ {children} - ); + ) }, -}); +}) diff --git a/packages/devui-vue/devui/checkbox/src/checkbox.tsx b/packages/devui-vue/devui/checkbox/src/checkbox.tsx index 0f9a0ab932430bc83b5a9d24817abd46fd5c53b1..d4bf54e8bdf7d00ecf5ba39fcf56d0dd36bcb5c0 100644 --- a/packages/devui-vue/devui/checkbox/src/checkbox.tsx +++ b/packages/devui-vue/devui/checkbox/src/checkbox.tsx @@ -1,62 +1,62 @@ -import { defineComponent, inject, computed } from 'vue'; -import './checkbox.scss'; +import { defineComponent, inject, computed } from 'vue' +import './checkbox.scss' import { checkboxGroupInjectionKey, checkboxProps, CheckboxProps, -} from './use-checkbox'; +} from './use-checkbox' export default defineComponent({ name: 'DCheckbox', props: checkboxProps, emits: ['change', 'update:checked', 'update:modelValue'], setup(props: CheckboxProps, ctx) { - const checkboxGroupConf = inject(checkboxGroupInjectionKey, null); - const isChecked = computed(() => props.checked || props.modelValue); + const checkboxGroupConf = inject(checkboxGroupInjectionKey, null) + + const isChecked = computed(() => props.checked || props.modelValue) const mergedDisabled = computed(() => { - return checkboxGroupConf?.disabled.value || props.disabled; - }); + return checkboxGroupConf?.disabled.value || props.disabled + }) const mergedChecked = computed(() => { - return checkboxGroupConf?.isItemChecked?.(props.value) ?? isChecked.value; - }); + return checkboxGroupConf?.isItemChecked?.(props.value) ?? isChecked.value + }) const mergedIsShowTitle = computed(() => { - return checkboxGroupConf?.isShowTitle ?? props.isShowTitle; - }); + return checkboxGroupConf?.isShowTitle.value ?? props.isShowTitle + }) const mergedShowAnimation = computed(() => { - return checkboxGroupConf?.showAnimation ?? props.showAnimation; - }); + return checkboxGroupConf?.showAnimation.value ?? props.showAnimation + }) const mergedColor = computed(() => { - return checkboxGroupConf?.color ?? props.color; - }); - const itemWidth = checkboxGroupConf?.itemWidth.value; - const direction = checkboxGroupConf?.direction.value; + return checkboxGroupConf?.color.value ?? props.color + }) + const itemWidth = checkboxGroupConf?.itemWidth.value + const direction = checkboxGroupConf?.direction.value const canChange = (isChecked: boolean, val: string) => { if (mergedDisabled.value) { - return Promise.resolve(false); + return Promise.resolve(false) } - const beforeChange = - props.beforeChange ?? checkboxGroupConf?.beforeChange; + const beforeChange = props.beforeChange ?? checkboxGroupConf?.beforeChange if (beforeChange) { - const res = beforeChange(isChecked, val); + const res = beforeChange(isChecked, val) if (typeof res === 'boolean') { - return Promise.resolve(res); + return Promise.resolve(res) } - return res; + return res } - return Promise.resolve(true); - }; + return Promise.resolve(true) + } const toggle = () => { - const current = !isChecked.value; - checkboxGroupConf?.toggleGroupVal(props.value); - ctx.emit('update:checked', current); - ctx.emit('update:modelValue', current); - ctx.emit('change', current); - }; + const current = !isChecked.value + checkboxGroupConf?.toggleGroupVal(props.value) + ctx.emit('update:checked', current) + ctx.emit('update:modelValue', current) + ctx.emit('change', current) + } const handleClick = () => { - canChange(!isChecked.value, props.value).then((res) => res && toggle()); - }; + canChange(!isChecked.value, props.label).then((res) => res && toggle()) + } return { itemWidth, @@ -67,7 +67,7 @@ export default defineComponent({ mergedChecked, mergedShowAnimation, handleClick, - }; + } }, render() { const { @@ -85,48 +85,48 @@ export default defineComponent({ value, mergedColor, $slots, - } = this; + } = this const wrapperCls = { 'devui-checkbox-column-margin': direction === 'column', 'devui-checkbox-wrap': typeof itemWidth !== 'undefined', - }; - const wrapperStyle = itemWidth ? [`width: ${itemWidth}px`] : []; + } + const wrapperStyle = itemWidth ? [`width: ${itemWidth}px`] : [] const checkboxCls = { 'devui-checkbox': true, active: mergedChecked, halfchecked, disabled: mergedDisabled, unchecked: !mergedChecked, - }; - const labelTitle = mergedIsShowTitle ? title || label : ''; + } + const labelTitle = mergedIsShowTitle ? title || label : '' const bgImgStyle = (mergedColor && halfchecked) || mergedColor ? `linear-gradient(${mergedColor}, ${mergedColor})` - : ''; + : '' const spanStyle = [ `border-color:${ (mergedChecked || halfchecked) && mergedColor ? mergedColor : '' }`, `background-image:${bgImgStyle}`, `background-color:${mergedColor && halfchecked ? mergedColor : ''}`, - ]; + ] const spanCls = { 'devui-checkbox-material': true, 'custom-color': mergedColor, 'devui-checkbox-no-label': !label && !$slots.default, 'devui-no-animation': !mergedShowAnimation, 'devui-checkbox-default-background': !halfchecked, - }; + } const polygonCls = { 'devui-tick': true, 'devui-no-animation': !mergedShowAnimation, - }; - const stopPropagation = ($event: Event) => $event.stopPropagation(); + } + const stopPropagation = ($event: Event) => $event.stopPropagation() const inputProps = { indeterminate: halfchecked, - }; + } return (
@@ -168,6 +168,6 @@ export default defineComponent({
- ); + ) }, -}); +}) diff --git a/packages/devui-vue/devui/checkbox/src/use-checkbox.ts b/packages/devui-vue/devui/checkbox/src/use-checkbox.ts index bef45c5a02722cd6b4dbf76774482d6728fd45b0..6a77a78fcad4560a2128829f3591b4fc8437ab18 100644 --- a/packages/devui-vue/devui/checkbox/src/use-checkbox.ts +++ b/packages/devui-vue/devui/checkbox/src/use-checkbox.ts @@ -1,72 +1,81 @@ -import { PropType, InjectionKey, Ref, ExtractPropTypes } from 'vue'; +import { PropType, InjectionKey, Ref, ExtractPropTypes } from 'vue' -type Direction = 'row' | 'column'; +type Direction = 'row' | 'column' const commonProps = { name: { type: String, - default: undefined + default: undefined, + }, + halfchecked: { + type: Boolean, + default: false, }, isShowTitle: { type: Boolean, - default: true + default: true, + }, + title: { + type: String, }, color: { type: String, - default: undefined + default: undefined, }, showAnimation: { type: Boolean, - default: true + default: true, }, disabled: { type: Boolean, - default: false + default: false, }, beforeChange: { - type: Function as PropType<(isChecked: boolean, v: string) => boolean | Promise>, - default: undefined - } -} as const; + type: Function as PropType< + (isChecked: boolean, v: string) => boolean | Promise + >, + default: undefined, + }, +} as const export const checkboxProps = { ...commonProps, halfchecked: { type: Boolean, - default: false + default: false, }, checked: { type: Boolean, - default: false + default: false, }, value: { type: String, }, label: { type: String, - default: undefined + default: undefined, }, title: { type: String, - default: undefined + default: undefined, }, 'onUpdate:checked': { type: Function as PropType<(v: boolean) => void>, - default: undefined + default: undefined, }, onChange: { type: Function as PropType<(v: boolean) => void>, - default: undefined + default: undefined, }, modelValue: { type: Boolean, }, 'onUpdate:modelValue': { - type: Function as PropType<(v: boolean) => void> - } -} as const; + type: Function as PropType<(v: boolean) => void>, + }, +} as const -export type CheckboxProps = ExtractPropTypes; +export type CheckboxProps = ExtractPropTypes export const checkboxGroupProps = { ...commonProps, @@ -76,36 +85,39 @@ export const checkboxGroupProps = { }, direction: { type: String as PropType, - default: 'column' + default: 'column', }, itemWidth: { type: Number, - default: undefined + default: undefined, }, options: { type: Array as PropType<({ value: string; } & Partial)[]>, - default: () => [] + default: () => [], }, onChange: { type: Function as PropType<(v: string[]) => void>, - default: undefined + default: undefined, }, 'onUpdate:modelValue': { type: Function as PropType<(v: string[]) => void>, - default: undefined - } -} as const; + default: undefined, + }, +} as const interface checkboxGroupInjection { disabled: Ref isShowTitle: Ref color: Ref showAnimation: Ref - beforeChange: undefined | ((isChecked: boolean, v: string) => boolean | Promise) + beforeChange: + | undefined + | ((isChecked: boolean, v: string) => boolean | Promise) toggleGroupVal: (v: string) => void isItemChecked: (v: string) => boolean itemWidth: Ref direction: Ref } -export const checkboxGroupInjectionKey: InjectionKey = Symbol('d-checkbox-group'); +export const checkboxGroupInjectionKey: InjectionKey = + Symbol('d-checkbox-group') diff --git a/packages/devui-vue/docs/components/checkbox/index.md b/packages/devui-vue/docs/components/checkbox/index.md index 035224a437642bc4ad4f117e8224fb227d201f98..c54b533366b2cfce131eaf766d7250763f81c7b7 100644 --- a/packages/devui-vue/docs/components/checkbox/index.md +++ b/packages/devui-vue/docs/components/checkbox/index.md @@ -8,61 +8,375 @@ 2. 单独使用可以表示在两个状态之间切换,可以和提交操作结合。 ### 基本用法 + :::demo ```vue - - + +``` + +::: + +### 使用 CheckBoxGroup + +:::demo + +```vue + + + ``` + ::: +### checkbox 根据条件终止切换状态 -#### 使用 CheckboxGroup +根据条件判断,label 为'条件判断回调禁止选中'的 checkbox 终止切换状态。 :::demo ```vue + +``` + +::: + +### checkbox-group 根据条件终止切换状态 + +选项包含'拦截'字段的 checkbox 无法切换状态。 +:::demo + +```vue + + ``` -::: \ No newline at end of file + +:::